In this script we estimate residual pool characteristics. The
residual pool is the pool that would form if streamflow were to decrease
to zero. Its depth is characterised as the elevation difference between
the pool’s deepest point and the pool outlet / riffle crest that
controls the flow of water out of the pool. It serves as a
flow-independent metric of pools in a stream and, with several
assumptions, we can estimate the depths, areas, and volumes of residual
pools based on our field data. See Lisle (1989) for more background on
the concept of residual depths.
We tried to make field data collection as simple as possible by
relying on water depths rather than elevations for our longitudinal
profiles, so that people could collect data without survey equipment -
reducing the cost and expertise required, and facilitating assessment in
densely vegetated / woody coastal streams, highly incised channels etc.
The use of simple depth data requires a couple of extra processing steps
compared with using elevation data, but luckily some rather clever
individuals have already figured it out.
The code we use here is adapted from the ‘Rapid Bed Profile’ approach
from Stack (1989), with additional guidance from Kaufman et al. (1999),
and we adopt Stack’s slope factor. The slope factor was developed in
coastal streams but has been applied successfully in a variety of other
systems. If you have the resources, the accuracy of the slope factor for
your particular system can be tested by comparing water-depth-derived to
elevation-derived residual pool data. However, even if this assumption
is untested (as it will be in most cases), the resulting metrics remain
valid for assessing changes within a system, as long as you don’t change
the slope factor between years or reaches in your comparison.
Data import
First we will import the tidied dataframe generated by the Data
Wrangling script, which was exported to your output folder. This file
has longitudinal thalweg water depth data that includes both regular
predetermined spacing and any ‘extra’ pool outlets and max pool depths
encountered (‘XPO’, ‘XD’). We proposed that the ‘extra’ measurements
were taken in the field, in order to capture the depth minima (potential
pool outlets) and maxima (deepest pool sections) that might occur
between regular intervals.
In this code we will require some additional constants that we ask
you to define in the code below based on data you recorded in the field
(or are able to estimate). This is done by creating a dataframe/table,
for which you must enter the following:
- names of each channel
- the years data were collected
- the standard interval spacing (in metres) for each reach and each
year
- the average reach slope (0.5 = 0.5%, not 50%) for each reach and
each year
- the average wetted width during low flow (in metres) for each reach
and each year.
Enter this information in the code below. Data is entered in vectors
of equal length and following the same sequence. For example, in the
existing code, Hatchery Channel is associated with spacing of 1 and 1,
slope of 1 and 1.1, and wetted width of 6.8 and 7.0, for 2024 and 2025
respectively. Once you create the dataframe with your data, check
through the table to ensure these constants are assigned to the correct
reach & year.
# Create a data frame to hold constants for multiple sites and years. Enter your data below:
constants_df <- data.frame(
Site = c("Hatchery Channel", "Hatchery Channel", "Brousseau Channel", "Brousseau Channel"), # Edit / Add your site names
year = c(2024, 2025, 2024, 2025), # Corresponding years for each site
spacing = c(1, 1, 1, 1), # spacing values for each site-year combination
Slope = c(0.5, 0.6, 0.5, 0.5), # Slope values for each site-year combination, in %
WetWidth = c(6.8, 7.0, 6.5, 7.1) # Average wetted width in m, for each site-year combination
)
# View the constants data frame
print(constants_df)
## Site year spacing Slope WetWidth
## 1 Hatchery Channel 2024 1 0.5 6.8
## 2 Hatchery Channel 2025 1 0.6 7.0
## 3 Brousseau Channel 2024 1 0.5 6.5
## 4 Brousseau Channel 2025 1 0.5 7.1
Creation of Residual Surfaces
The residual surface is the water surface at the point when
streamflow approaches zero, and residual depth is the vertical distance
between the residual surface and the stream bed. As such, when we
estimate residual pools and residual depths, these are features that are
independent of flow conditions at the time of the field survey. While
they might be representative of actual pool conditions during times of
very low flow, their value lies with the ability to make comparisons of
pool habitat among years and/or reaches without quantifying and
controlling for variable flow conditions.
Our code uses the sequence of thalweg depth measurements to identify
potential pool outlets in the sampled reach, and estimates residual
depths at each measurement location based on a projected residual
surface that extends upstream from each pool outlet. The residual
surface is projected using the expected pool water surface slope (which
is estimated using Stack’s empirical equation, incorporating the average
reach slope that you entered as a constant).
It is important to note that when we identify pool outlets or riffle
crests (either in the field or using this code), we usually base this
determination on the bed elevation and/or water depth at the current
location compared with the areas immediately adjacent. However, a
potential pool outlet will not ‘behave’ as a pool outlet under all flow
conditions: it could be high and dry under very low flow conditions, or
it could itself be within a pool due to the backwatering effects of a
higher-elevation pool outlet downstream. From here onward, we will use
the term ‘local depth minima’ (‘LDM’ in code) to refer to
locations that have the potential to be pool outlets - that is, they are
less deep than areas immediately downstream and upstream, accounting for
the slope of the stream. We will reserve the term ‘pool outlet’ for
cases when local depth minima would be expected to actually backwater a
pool under flow conditions approaching zero.
At this point our code will generate a new dataframe (residuals.df)
with the local depth minima identified and the residual surface
projected. If you are interested in how this is done, check out the R
code. For everyone else, here are some fish:
🐟🐟🐟🐟🐟 🐟🐟🐟🐟🐟 🐟🐟🐟🐟🐟 🐟🐟🐟🐟🐟 🐟🐟🐟🐟🐟 🐟🐟🐟🐟🐟
🐟🐟🐟🐟🐟 🐟🐟🐟🐟🐟 🐟🐟🐟🐟🐟
Below we generate a quick visual of the depths and residual surfaces
that were projected by the code. Take a look to ensure it matches your
understanding of residual pools and look for potential errors (the
figure is interactive, so zoom in if you have several plots). Try to
identify some local depth minima that are within a pool (if present in
your data), and compare these to the local depth minima that act as pool
outlets - the shallower features at which residual surfaces begin.
Remember that the residual surface slopes down in these figures as you
progress upstream (right in the plots), which is to compensate for the
fact that the true thalweg surface slopes down as you progress
downstream.
‘Meaningful’ Pools
Consider the vertical exaggeration of the above figure - some ‘pools’
may be very shallow indeed, and might not necessarily correspond with
what you would actually consider a pool in a stream.
It is probably most informative to consider metrics relating only to
those pools that are expected to be hydraulically and/or biologically
meaningful. The code now detects pools and assigns each a pool ID, so
that we can characterise them individually and select subsets as
appropriate.
The above figure should show a series of distinct pools and is
exported to your output folder. Don’t worry if the shading cuts off
before the pool’s upstream extent, this is just an artefact associated
with my limited figure-plotting abilities. The important thing to note
is that the calculations below will integrate the full area beneath the
residual surface for each pool.
Pool Metrics
The code now calculates the following metrics for each residual
pool:
Sagittal refers to a plane that divides a body into left and right,
so imagine a two-dimensional vertical screen extending downstream all
along the thalweg, separating river left from river right. Within each
residual pool, the sagittal area corresponds to the surface area of that
screen. Too abstract? Take a look at the above figure again: Each of the
shaded areas corresponds to the sagittal area for that particular
residual pool - sagittal area integrates each depth measurement over the
length of the pool. Although this may not be as intuitive as pool
volume, it requires fewer assumptions than will be necessary to generate
estimates of pool volume (i.e., regarding cross-sectional channel shape
of pools at zero flow, wetted widths). Because fewer assumptions are
required, and because it easily corresponds to 2D visualisations like
the one above, we recommend using sagittal area rather than volume for a
metric tracking changes in pool habitat (though we will also calculate
volume later).
Subsetting Pools
So far we have identified all of the residual pools, but depending on
your dataset some of the pools visualised above might look more like
puddles. So to focus our summary statistics on pools that better align
with what we consider biologically- and/or geomorphically-meaningful, we
can use the metrics we just calculated to focus on a specific subset of
deeper pools.
In terms of subsetting pools, some people use a specific depth
cut-off for a species of interest (e.g., Mossop and Bradford 2006 used
0.1 m). Alternatively the pools that we focus on can be based on
physical characteristics of the sampled reach. We will do the latter,
keeping this code more widely applicable, by following Stack (1989) who
determined meaningful pools as those that had a maximum depth greater
than or equal to the standard deviation of depth for the reach.
In the following code chunk it reads ‘custom_depth <- NULL’. This
is our default subsetting (selects only pools with a maximum residual
depth greater than the standard deviation of the residual depths for the
entire sampled reach). If you want to subset the pools in another way,
you can modify the code here. For example, if it is biologically
meaningful for your system to consider only pools that are 0.1 m deep or
greater during approaching-zero-flow periods, you can specify
‘custom_depth <- 0.1’. Or, if you want to consider all pools no
matter how shallow, then assign custom_depth a value of ‘0’. Just be
sure to compare like-for-like when you consider different years/sites
that you may wish to compare.
# Add a custom depth threshold in metres, or leave as 'NULL' to use standard deviation. If you are interested in all of the residual depths (i.e., not subsetting), just enter '0' for the custom_depth
custom_depth <- NULL
The table above has been exported to your output folder. It displays
the subset selection of residual pools, the sagittal area of each pool,
the maximum residual depth (deepest point per pool at zero flow), and
the pool length of each pool. When considered at the reach-scale,
summary statistics of the maximum residual depth and pool length have
been considered useful metrics to track pool quality and quantity (e.g.,
Lisle 1986, Mossop and Bradford 2006, Clark et al 2019).
The reach mean of the pool maximum residual depths has been used as a
proxy for pool quality, and positive relationships with Chinook salmon
density have been demonstrated (e.g., Mossop and Bradford 2006).
Relationships between habitat metrics and biota can be highly
context-dependent, and independent verification is recommended where
possible. However, as the resources required to test these assumptions
are often prohibitive, we recommend taking advantage of relationships
that have already been quantitatively demonstrated in the scientific
literature. Although it is possible to generate quantitative
estimates of biotic densities if the relationship between habitat metric
and biotic density is monotonic, we feel that this is too speculative
without data for your individual system. However, for the purpose of
restoration monitoring, we feel it is incredibly powerful to be able to
demonstrate (e.g.) that we have caused an x-sized increase in a
habitat metric that is known to be positively correlated with target
species density in a similar system.
The proportional length of pools in the reach also has demonstrated
positive relationships with coho, Chinook densities (Clark et al 2019).
Bear in mind that there will always be nuance involved in the
application and interpretation of habitat metrics. You must understand
and predict, in an a priori fashion, what your restoration
objectives are with respect to habitat: Does your reach need more pool
of a certain depth? Is your reach lacking much-needed riffles?
Presumably there are cases where the reach has too much pool habitat.
These types of questions are best addressed with well-matched reference
sites, but local knowledge and the scientific literature will also be of
great help.
We will now generate and export to your output folder some summary
statistics, including the aforementioned mean max residual depth and
length in residual pool, for your data:
These above statistics should be useful for tracking changes over
time, or comparing reference / control reaches. Because they are all
based on residual depths, they are flow-independent.
Total sagittal area and proportion of the reach length in residual
pool should be compared between years and/or sites, and you can
interpret whether the changes are in the predicted direction and of a
meaningful magnitude. Since these two metrics have one value per reach,
the metrics themselves cannot be evaluated statistically (unless you
have a large number of reaches/years), however a directional change over
time that aligns with your predictions is obviously quite a good
sign.
Inferential Tests
We can apply inferential statistical tests to the sagittal area,
maximum pool depth, and pool length data - that is, the data which have
values at the level of each pool (i.e., a population of values is
available per reach/year). We will use inferential statistical tests to
determine whether the differences we observed among reaches and years
are likely to be due to chance. You will be familiar with p values of
0.05 (observed result expected just due to chance 1 in 20 times) and we
will use p=0.05 as our cut-off here. However, depending on your adaptive
management plans, you may be willing to accept different levels of
certainty, and p values of 0.1 are not unheard of in restoration
projects. This all depends on the risk tolerance of you and your team,
and should be established before conducting analyses.
For these inferential tests we will use ANOVAs because of their
familiarity for ecologists and expected suitability for the data. For
the metrics relating to residual pools that we have generated, we will
test for differences between sites, years, and an interaction of
sites*years (i.e., did the different locations change differently over
time). The code uses the subset of pools that were defined earlier as
‘meaningful’.
Choice of Metric: At this point, you should choose
which of ‘sagittal area’, ‘maximum pool depth’, and ‘pool length’ best
aligns with your needs (e.g., relevance to restoration objective,
comparisons with literature, ease of communication). You will base your
interpretation of the ANOVA on this chosen metric, even though we will
run ANOVA for all three.
The reason for selecting one metric for interpreting your hypothesis
is that the metrics are not independent of one another: Sagittal area
incorporates depth and length components, and all three metrics are
connected in the stream; if you used a subset of the residual pools, all
metrics inherently include some information about depth. If you were to
continue without deciding upon a metric, it would be too tempting to
come up with post-hoc explanations (e.g., if sagittal area increased but
not depth or length). You should certainly consider potential
implications of your results (carefully), but in terms of evaluating the
success of your project, it is important that you decide in advance
which metric change = success.
Although it may be possible to run a MANOVA test (which can
accommodate correlated dependent variables) using all three metrics
together, MANOVA tests typically require larger sample sizes than we
anticipate for many reach surveys. Therefore, we stick with multiple
ANOVAs with a large dose of caution.
Assumption Robustness
Whenever applying statistical tests, we should ensure that our data
is suitable, in that it meets the assumptions of the intended
inferential test. For ANOVAs the assumptions are:
Data in different groups should be independent:
One of your sites must not cause changes in another (though both
sites experiencing shared ‘external’ causal factors, such as being in
the same watershed, is acceptable). This is hopefully accounted for by
good selection of impact/control/reference sites.
You may note that no site is actually independent from that same
site in the past. For longer time-series we would need to adopt a
different inferential approach to avoid autocorrelation, but here we are
dealing with simple before vs after comparisons, and it is widely
accepted that ANOVAs are suitable for before/after comparisons if the
comparison is balanced (e.g., 2 years of before data compared with 2
years of after data).
Residuals are normally distributed: In this case we mean
residuals more broadly - the difference between each datapoint and the
mean. We will examine this assumption using Q-Q plots and the
Shapiro-Wilk normality test.
Homoscedasticity: Variance should be broadly equal across all
groups. We will test this with Levene’s test.
If any of these assumptions are violated, we can transform the data
and test whether the transformed data (log-, arcsine- etc.) satisfies
the assumptions. If this is not an option, we should seek a more
suitable statistical test (e.g. Welch’s ANOVA or mixed-effects
models).
The tests of assumptions are carried out below, after we specify the
before and after data that you wish to compare.
Before / After Years
Enter your before and after years in the below code, you may have
more than one year in each category. Remember that these should balance
(equal number of years before as after), but they need not be
consecutive years. If you do not have balanced data (e.g., only one year
was possible before project implementation) be very cautious in running
and interpreting an ANOVA. You could select only a subset of your data
to keep the comparison balanced, but if you do this for more than one
set of dates you must account for the multiple comparisons inflating the
likelihood of a Type I error (false positive).
# Define "Before" and "After" years
before_years <- c(2024) #add more years inside brackets if needed, e.g. 'c(2024, 2025, 2026)'
after_years <- c(2025) #add more years inside brackets if needed, e.g. 'c(2027, 2029, 2036)'
The next section of code generates tests and figures that you should
review to ensure your data are suitable for an ANOVA. In brief, look for
the following:
- Boxplots: consider whether outliers (dots) are real or errors
- Q-Q plots: a reasonably straight line of points means alignment with
normal distribution
- Normality test (Shapiro-Wilk): p<0.05 indicates
non-normality
- Levene’s test: p<0.05 indicates that variance among groups
differs
- Skewness values < 0 are left skewed, > 0 right skewed.
Kurtosis values < 3 light-tailed, > 3 heavy-tailed.






Normality Test Results for Pool Summary Data
| Brousseau Channel |
After |
0.700 |
0.346 |
0.507 |
Normality test completed |
| Hatchery Channel |
After |
0.430 |
0.325 |
0.977 |
Normality test completed |
| Brousseau Channel |
Before |
0.471 |
0.129 |
0.086 |
Normality test completed |
| Hatchery Channel |
Before |
0.172 |
0.081 |
0.051 |
Normality test completed |
##
## --- Levene's Test Results for sagittal_area ---
## Levene's Test for Homogeneity of Variance (center = median)
## Df F value Pr(>F)
## group 3 6.2061 0.002838 **
## 24
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## --- Levene's Test Results for max_residual_depth ---
## Levene's Test for Homogeneity of Variance (center = median)
## Df F value Pr(>F)
## group 3 2.9027 0.05559 .
## 24
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## --- Levene's Test Results for pool_length ---
## Levene's Test for Homogeneity of Variance (center = median)
## Df F value Pr(>F)
## group 3 1.7929 0.1754
## 24
## Variable Skewness Kurtosis
## sagittal_area sagittal_area 1.7710682 4.904845
## max_residual_depth max_residual_depth 0.8824034 2.069536
## pool_length pool_length 1.3271828 4.412251
If, based on the above evaluation, your data appear to be unsuitable
for the intended inferential test you may wish to use an alternative
non-parametric test or transform the data. We provide some assistance
for transformations here, but this part may require some more work on
your part since we cannot predict what your data will need.
As an example, our data appeared normally distributed (p>0.05
Shapiro-Wilk) but Levene’s test revealed that sagittal area variance was
unequal across site-years (p<0.05). We therefore log-transformed the
sagittal area data and re-ran the above diagnostics, with Levene’s test
returned as non-significant and therefore acceptable to be used in
ANOVAs. Note that only those metrics that do not meet the assumptions
need to be transformed.
The code we used for the transformation is below. If you need to
transform the data, follow these steps:
ANOVA
Once you have satisfied yourself that your data (or transformed data)
are suitable, we will run the inferential tests. We use ANOVA to ask
whether the following metrics differ among sites, years, and site*year
interactions:
- Sagittal area
- Maximum residual depth
- Pool length
If you did use transformed data, ensure you reference that variable
in the below code (e.g., change “sagittal_area” to
“transformed_sagittal_area”)
# Function to run ANOVA for a given variable
run_anova <- function(data, variable) {
formula <- as.formula(paste(variable, "~ Site * Time_Category"))
anova_result <- aov(formula, data = data)
summary(anova_result)
}
# Ensure transformed data is used in the ANOVA if necessary (change the variable name in quotation marks in these next rows)
anova_max_residual_depth <- run_anova(pool_summary_filtered, "max_residual_depth")
anova_pool_length <- run_anova(pool_summary_filtered, "pool_length")
anova_sagittal_area <- run_anova(pool_summary_filtered, "sagittal_area")
## [1] "_______________ANOVA for Max Residual Depth______________"
## Df Sum Sq Mean Sq F value Pr(>F)
## Site 1 0.072 0.072 2.907 0.1011
## Time_Category 1 3.712 3.712 150.194 8.07e-12 ***
## Site:Time_Category 1 0.115 0.115 4.642 0.0415 *
## Residuals 24 0.593 0.025
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## [1] "_______________ANOVA for Residual Pool Length______________"
## Df Sum Sq Mean Sq F value Pr(>F)
## Site 1 6 6.0 0.038 0.84625
## Time_Category 1 2022 2021.5 12.868 0.00148 **
## Site:Time_Category 1 163 163.4 1.040 0.31792
## Residuals 24 3770 157.1
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## [1] "_______________ANOVA for Residual Pool Sagittal Area______________"
## Df Sum Sq Mean Sq F value Pr(>F)
## Site 1 31.6 31.6 0.675 0.419
## Time_Category 1 1388.2 1388.2 29.659 1.35e-05 ***
## Site:Time_Category 1 6.3 6.3 0.134 0.718
## Residuals 24 1123.3 46.8
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Take some time to ensure you understand what the above tells you,
particularly with regards to your chosen metric of success. In the
example ANOVA above, there was one site:time interaction that was
significant at p=0.05 (maximum residual depth), and the time category
was significant for all metrics. This suggests that a change in metrics
over time was not likely due to chance, but only for maximum residual
depth did our restoration site change over time differently than the
control site. However, we chose sagittal area as our a priori
success metric, so we cannot interpret this as a successful restoration
action at this point in time.
Although we could not discard our alternative hypothesis (that
changes at our restoration site were not due to our actions), we may
still learn from the above to inform future plans. Consider all the
information we have generated so far for you data, and take some time to
think about it. Step outside to do this if you are able to. Consider
what it might mean if pools at our restoration site appear deeper on
average, but sagittal areas did not change? Consider whether there are
pools that did or did not scrape through the subsetting cut-off (i.e.,
very small pools of marginal value), how might they impact your mean
values? Was there a big enough change in these marginal cases to create
statistical significance? Is any of this biologically or geomorphically
meaningful based on your hypotheses?
This is all endlessly interesting/maddening (depending on your
perspective) and we highly recommend finding another person (or several)
to talk it through with. Before moving on to further analyses, ensure
you have a reasonable understanding of the information so far. Take a
step back to think about the big picture.
Volume Estimation
If you have no hypotheses or predictions specifically regarding pool
volumes, you may wish to skip this section and move onto
Fine Sediment in Pools.
If you took wetted width measurements at transects along the reach,
you can use the average to estimate the volume of residual pools. This
approach is a more simplified approach than that of Robison (1998) who
linked wetted width measurements to nearby longitudinal intervals. If
this is possible for the data you collected, we recommend reviewing
Robison (1998) to obtain more ‘localised’ estimates of wetted width.
However, bear in mind that there may regardless be a bias in residual
wetted widths if (e.g.) pools tend to be wider than riffles. For our
simplified approach we assume that the wetted width is constant for the
reach, and we also assume that the stream cross sections are perfect
triangles. We then use the ratio of residual depths to field-recorded
depths to estimate the residual wetted widths of pools when flow
approaches zero.
Considering changes in (coarsely-estimated) pool volume can be of
interest due to the potential for natural processes to alter both the
longitudinal and cross-sectional heterogeneity of a stream. For example,
perhaps we are anticipating a narrower wetted channel with deeper pools,
and want to explore what this means for pool volume. However, as
suggested by the coarse assumptions we made for this calculation,
interpret results with caution.
The above table lists the volume estimates for each of the
‘meaningful’ subset of residual pools, and this table is also exported
to your output folder. Next we will display and export a table with some
key summary statistics for the reach: Total volume of residual pools,
and the mean and standard deviation residual volume of pools.
Inferential Tests - Volume
Following the same approach as for the one- and two-dimensional pool
metrics, we will use ANOVAs to test the pool volume differences between
sites and years.
Assumption Robustness
As before, the first step is to check whether an ANOVA is suitable
for the variables.
Normality Test Results for Pool Volume Data
| Brousseau Channel |
After |
0.500 |
Normality test completed |
| Hatchery Channel |
After |
0.461 |
Normality test completed |
| Brousseau Channel |
Before |
0.451 |
Normality test completed |
| Hatchery Channel |
Before |
0.014 |
Normality test completed |
## Levene's Test for Homogeneity of Variance (center = median)
## Df F value Pr(>F)
## group 3 6.9518 0.001577 **
## 24
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1


## Skewness: 1.814195
## Kurtosis: 5.117599
We needed to transform our volume data, which was not normally
distributed. Following the same transformation steps as before, We
replaced ‘pool_volume_m3’ with the log-transformed
‘transformed_pool_volume_m3’ (using the below code) and re-ran the
diagnostics. Our Q-Q plot and tests looked much better, so we used the
transformed variable in the ANOVA.
# Define transformations as a named list for pool volume
transformations <- list(
pool_volume_m3 = function(x) ifelse(x > 0, log(x), NA) # Log transformation with handling for non-positive values (volumes should all be positive!)
)
# Apply transformations and update the dataframe
pool_volumes_filtered <- apply_transformations(pool_volumes_filtered, transformations)
ANOVA - volume
# Ensure transformed data is used in the ANOVA function if necessary (change the variable name in quotation marks)
anova_pool_volumes <- run_anova(pool_volumes_filtered, "pool_volume_m3") # adjust to "transformed_pool_volumes_m3" as needed
## Df Sum Sq Mean Sq F value Pr(>F)
## Site 1 4 4 0.014 0.907
## Time_Category 1 9095 9095 33.011 6.39e-06 ***
## Site:Time_Category 1 231 231 0.839 0.369
## Residuals 24 6613 276
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
When interpreting potential changes in pool volume metrics, remember
that we needed to make assumptions regarding the widths of residual
pools, making these volume metrics more speculative than sagittal area
metrics. While volumes can be useful for interpretation, if there are
disagreements between the inferential test results among volume- and
area/length-based metrics, we recommend defaulting to the latter
(unless, of course, you have a solid a priori hypothesis and
prediction that suggests volume should differ in the way you
observed).
Fine Sediment in Pools
The longitudinal survey included presence/absence observations of
fine sediment along the thalweg. Here we will generate a metric of the
proportion of residual pool thalweg that features fine sediments.
Note that, while the previous metrics in this script use the ‘custom
depth’ threshold to subset what are considered ‘meaningful’ pools, we
recommend considering fine sediment relative to the full contingent of
residual pools that the code has identified. Our rationale is that the
fines metrics relate more closely to the mechanisms that can be
responsible for making pools ‘meaningful’ (or not) in terms of fish
habitat availability. If we were to look at the proportion of fines only
in ‘meaningful’ (deep enough) pools, we might miss pools that are closer
to being ‘not pools’ (i.e., recently filling-in or scouring of
sediment). Of course, when pools are fully infilled with sediment they
will not be detected as pools at all, but the ability to recognise when
a pool is filling in (or scouring out) may be an important indicator of
restoration success, or a trigger for adaptive management actions.
However, should it be of greater interest for your project, we have
included in the code below the ability to select a subset of pools.
Consistent with the previous custom depth threshold, you can add a
specified depth in metres, or enter ‘NULL’ to select only pools with a
maximum residual depth greater than the standard deviation of the
residual depths for the entire sampled reach. Our default is 0 (no
subsetting).
# Define custom threshold if required. We recommend 0 (all residual pools, regardless of maximum depth)
custom_depth <- 0 # Replace with your desired threshold in metres, or set to NULL to use the standard deviation of the reach (that year)
Brousseau Channel - Pool Fine Sediment
|
Site
|
year
|
pool_id
|
pool_length
|
fines_length
|
fines_proportion
|
|
Brousseau Channel
|
2024
|
1
|
21.5
|
21.0
|
0.977
|
|
Brousseau Channel
|
2024
|
2
|
0.5
|
0.5
|
1.000
|
|
Brousseau Channel
|
2024
|
3
|
21.5
|
17.5
|
0.814
|
|
Brousseau Channel
|
2024
|
4
|
0.5
|
0.5
|
1.000
|
|
Brousseau Channel
|
2024
|
5
|
0.5
|
0.0
|
0.000
|
|
Brousseau Channel
|
2024
|
6
|
8.5
|
5.0
|
0.588
|
|
Brousseau Channel
|
2024
|
7
|
4.5
|
4.5
|
1.000
|
|
Brousseau Channel
|
2024
|
8
|
8.5
|
7.0
|
0.824
|
|
Brousseau Channel
|
2024
|
9
|
2.5
|
1.0
|
0.400
|
|
Brousseau Channel
|
2024
|
10
|
22.5
|
20.0
|
0.889
|
|
Brousseau Channel
|
2024
|
11
|
1.5
|
0.5
|
0.333
|
|
Brousseau Channel
|
2024
|
12
|
2.5
|
1.0
|
0.400
|
|
Brousseau Channel
|
2024
|
13
|
2.5
|
0.0
|
0.000
|
|
Brousseau Channel
|
2024
|
14
|
12.5
|
8.0
|
0.640
|
|
Brousseau Channel
|
2024
|
15
|
3.5
|
3.5
|
1.000
|
|
Brousseau Channel
|
2024
|
16
|
6.5
|
6.5
|
1.000
|
|
Brousseau Channel
|
2025
|
1
|
61.0
|
50.5
|
0.828
|
|
Brousseau Channel
|
2025
|
2
|
18.0
|
13.0
|
0.722
|
|
Brousseau Channel
|
2025
|
3
|
33.0
|
23.0
|
0.697
|
|
Brousseau Channel
|
2025
|
4
|
30.0
|
21.5
|
0.717
|
|
Brousseau Channel
|
2024
|
Total
|
120.0
|
96.5
|
0.804
|
|
Brousseau Channel
|
2025
|
Total
|
142.0
|
108.0
|
0.761
|
Hatchery Channel - Pool Fine Sediment
|
Site
|
year
|
pool_id
|
pool_length
|
fines_length
|
fines_proportion
|
|
Hatchery Channel
|
2024
|
1
|
24.5
|
0.0
|
0.000
|
|
Hatchery Channel
|
2024
|
2
|
13.5
|
0.0
|
0.000
|
|
Hatchery Channel
|
2024
|
3
|
10.5
|
0.0
|
0.000
|
|
Hatchery Channel
|
2024
|
4
|
5.5
|
0.0
|
0.000
|
|
Hatchery Channel
|
2024
|
5
|
30.5
|
29.0
|
0.951
|
|
Hatchery Channel
|
2024
|
6
|
11.5
|
11.5
|
1.000
|
|
Hatchery Channel
|
2024
|
7
|
12.5
|
12.5
|
1.000
|
|
Hatchery Channel
|
2024
|
8
|
8.5
|
8.5
|
1.000
|
|
Hatchery Channel
|
2024
|
9
|
9.5
|
9.5
|
1.000
|
|
Hatchery Channel
|
2024
|
10
|
1.5
|
0.0
|
0.000
|
|
Hatchery Channel
|
2025
|
1
|
39.0
|
0.0
|
0.000
|
|
Hatchery Channel
|
2025
|
2
|
19.0
|
0.0
|
0.000
|
|
Hatchery Channel
|
2025
|
3
|
1.0
|
0.0
|
0.000
|
|
Hatchery Channel
|
2025
|
4
|
57.0
|
55.5
|
0.974
|
|
Hatchery Channel
|
2025
|
5
|
24.0
|
20.5
|
0.854
|
|
Hatchery Channel
|
2024
|
Total
|
128.0
|
71.0
|
0.555
|
|
Hatchery Channel
|
2025
|
Total
|
140.0
|
76.0
|
0.543
|
The above tables (also exported to output folder) include a final row
for each site-year with reach total pool length, reach total pool length
with fine sediment, and the reachwide proportion of pools with fines (a
ratio from 0 to 1). Comparison of the reachwide proportion alone may be
sufficient to demonstrate project effectiveness, perhaps complemented
with the figure that we will create below. However, if you would like to
statistically compare how fine sediment changed over time compared with
a control, we can look at the distributions of underlying pool data (the
fines_proportion data for every pool).
Inferential Tests - Fines
This time, we are dealing with data that are bounded by 0 and 1. And
in many cases, we also anticipate a relatively high frequency of 0s (no
fines in pools) and/or 1s (fines throughout). We are confident that
non-transformed data would violate the assumptions of ANOVA, so we omit
the initial diagnostic tests. Our attempts to arcsine-transform the data
were not successful, as our transformed data remained non-normally
distributed with significant heteroscedasticity. As such, and since we
suspect our fines data distribution is not particularly unusual, we
opted for Beta regression.
Slightly nerdy bit, feel free to ignore: Beta regressions are capable
of dealing with non-normal heteroscedastic data. Although they cannot
actually handle 0’s and 1’s, for our case they are preferable over
two-part models (e.g. hurdle models): Since an observation of “no fine
sediment” could very plausibly be recorded where 2 cm of fine sediment
was actually present in a 20 m pool, we are comfortable adjusting the
0’s and 1’s to 0.001 and 0.999. We feel a hurdle model would excessively
complicate interpretability (e.g. a binomial fines presence/absence
mechanism plus a fines quantity mechanism). See Geissinger et al 2022 if
interested.
We will generate a frequency plot of the fine proportion data, fit
the Beta regression, and plot the frequency distribution of the
residuals (which should be broadly symmetrical around zero) and their
relationships to the fitted values (for which no clear relationship or
heteroscedasticity should be evident). We will only export the results
of the Beta regression to your output folder.

## Warning in betareg.fit(X, Y, Z, weights, offset, link, link.phi, type, control,
## : no valid starting value for precision parameter found, using 1 instead


##
## Call:
## betareg(formula = fines_proportion_adjusted ~ Site * Time_Category, data = fines_proportion_filtered)
##
## Quantile residuals:
## Min 1Q Median 3Q Max
## -1.6659 -0.7903 0.0613 1.0070 1.4205
##
## Coefficients (mean model with logit link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 0.2570 0.6770 0.380 0.704
## SiteHatchery Channel -0.9495 0.9034 -1.051 0.293
## Time_CategoryBefore 0.1700 0.7544 0.225 0.822
## SiteHatchery Channel:Time_CategoryBefore 0.4271 1.0473 0.408 0.683
##
## Phi coefficients (precision model with identity link):
## Estimate Std. Error z value Pr(>|z|)
## (phi) 0.52358 0.09579 5.466 4.61e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Type of estimator: ML (maximum likelihood)
## Log-likelihood: 54.34 on 5 Df
## Pseudo R-squared: 0.1048
## Number of iterations: 20 (BFGS) + 2 (Fisher scoring)
Since you may not be familiar with Beta regression, here are some
basics on interpretation for the test output:
“Optimization failed to converge…” If you see this warning, it
may be that there were 0 values across an entire Site. This should be
fairly easy to interpret without inferential tests.
Quantile residuals measure the difference between the actual data
and predicted values. The median should be close to 0. Also check the
residuals vs fitted plot to ensure there is no clear trend or unusual
outliers
Coefficients (mean model): these are the effects of the
predictors (site, time) on the response variable (fine sediment
proportion in pools). Look for significant p values in the last
column, particularly for the Site_____:Time_Category_____ row, which is
the interaction term (if significant, this means the proportion of fines
in residual pools changed over time differently between
sites).
Phi coefficients: there is a p-value here as well, but this
refers to whether the spread of the data around the mean was an
important feature. If the phi estimate is very high, this means the data
was concentrated around the mean (fines proportion doesn’t fluctuate
much between sites/times). Consider phi of 0.1 to be spread out data, 1
to be moderate, and 10 to be concentrated around the mean.
Pseudo R-squared: this is how much of the variation in fines in
pools can be explained by the site and time variables. Often low in
ecological contexts.
Proportional data can be less intuitive to interpret, and using an
unfamiliar inferential test might not clear things up. Not to worry:
After we perform a similar analysis with the aquatic vegetation data, we
will create some plots that show the distribution of fines and aquatics
across the reach. These plots are more intuitive and will help you to
interpret any changes in greater context.
Aquatic Vegetation in Pools
In the field, you may have also estimated the proportion of the
wetted width that was occupied by aquatic vegetation. During data
wrangling we added three new data columns to facilitate analyses of
these aquatic vegetation observations: subveg (submerged vegetation),
floatveg (floating vegetation), and emergveg (emergent vegetation). We
will use these variables to estimate the length and plan area of each
residual pool that would be occupied by aquatic vegetation when flows
approach zero. These can be useful metrics for tracking habitat quality
and mechanisms of habitat change, however plan area estimates come with
a caveat:
In estimating plan areas of vegetation, we assume that the proportion of
residual pool width occupied by vegetation is equal to the proportion of
the wetted width that was occupied in the field. In most cases this will
be an overestimate because the thalweg will typically have less
vegetation and, as flows recede, the thalweg makes up a greater
proportion of the wetted width. Although vegetated residual pool areas
can be useful for tracking changes over time, because they are based on
proportions of wetted widths, you should not consider them
flow-independent. When interpreting changes over time (or from different
reaches), remember that if flows were notably different, then the amount
of submerged vegetation can differ. If you had the time/ability to
collect wetted width measurements at each interval this could be used to
control for this variation by adding it as a covariate in the
inferential test. Otherwise, interpret with caution.
Aside from the above, in some cases it can also be difficult to
assign proportions consistently in the field, such as when invasive reed
canarygras forms dense mats that obscure banks and underlying
soils/substrates. If there were such difficulties in the field, these
should be clearly stated to aide interpretation. For the purposes of
interpretation, remember that in this section we are considering the
proportions of the length and the area of residual pools that
are occupied by aquatic vegetation. As such, the field observations
should relate to proportions of wetted width (not bankfull), because at
flows approaching zero the vegetation between observed wetted width and
bankfull width would not occupy any part of the residual pool.
🌿🌿🌿🌿🌿 🌿🌿🌿🌿🌿 🌿🌿🌿🌿🌿 🌿🌿🌿🌿🌿 🌿🌿🌿🌿🌿 🌿🌿🌿🌿🌿
🌿🌿🌿🌿🌿 🌿🌿🌿🌿🌿 🌿🌿🌿🌿🌿
The tables generated and exported by the code below will show the
proportional length of residual pools in which aquatic vegetation was
present (regardless of quantity/width), in the same way that we used the
fines data. The tables also show the plan area of residual pools that
featured aquatic vegetation, based on your estimates of the proportion
of wetted width occupied by vegetation at each interval, integrated
along the length of each pool.
Just like for fines, for aquatic vegetation we default to using the
full contingent of pools. Our rationale is that vegetation (particularly
certain problematic invasive species) can be involved in the process of
infilling pools by trapping sediment, and it may be of restoration
significance to track changes in vegetation in minor nascent or
infilling pools. However, as before, we have included in the code below
the ability to select a subset of pools, for example if you want to
focus on factors such as the importance of aquatic vegetative cover that
would plausibly be used by rearing fish in summer (i.e., only in pools
of a certain depth). Our default is 0 (no subsetting), and if you change
it, ensure that when comparing systems or years you are comparing like
for like.
# Define custom threshold if required. We recommend 0 (all residual pools, regardless of maximum depth)
custom_depth <- 0 # Replace with your desired threshold in metres, or set to NULL to use the standard deviation of the reach (that year)
Reachwide Submerged Vegetation for Each Site-Year
| Brousseau Channel_2024_Total |
Brousseau Channel |
2024 |
Total |
128 |
0 |
0.0000000 |
0.0000000 |
| Brousseau Channel_2025_Total |
Brousseau Channel |
2025 |
Total |
142 |
0 |
0.0000000 |
0.0000000 |
| Hatchery Channel_2024_Total |
Hatchery Channel |
2024 |
Total |
133 |
112 |
0.8421053 |
0.8398496 |
| Hatchery Channel_2025_Total |
Hatchery Channel |
2025 |
Total |
140 |
117 |
0.8357143 |
0.8321429 |
Reachwide Emergent Vegetation for Each Site-Year
| Brousseau Channel_2024_Total |
Brousseau Channel |
2024 |
Total |
128 |
0 |
0 |
0 |
| Brousseau Channel_2025_Total |
Brousseau Channel |
2025 |
Total |
142 |
0 |
0 |
0 |
| Hatchery Channel_2024_Total |
Hatchery Channel |
2024 |
Total |
133 |
0 |
0 |
0 |
| Hatchery Channel_2025_Total |
Hatchery Channel |
2025 |
Total |
140 |
0 |
0 |
0 |
Reachwide Floating Vegetation for Each Site-Year
| Brousseau Channel_2024_Total |
Brousseau Channel |
2024 |
Total |
128 |
10 |
0.0781250 |
0.0781250 |
| Brousseau Channel_2025_Total |
Brousseau Channel |
2025 |
Total |
142 |
10 |
0.0704225 |
0.0704225 |
| Hatchery Channel_2024_Total |
Hatchery Channel |
2024 |
Total |
133 |
41 |
0.3082707 |
0.0748120 |
| Hatchery Channel_2025_Total |
Hatchery Channel |
2025 |
Total |
140 |
43 |
0.3071429 |
0.0737500 |
Inferential Tests - Aquatic Veg
Just like with the fines data, we are dealing with data that are
bounded by 0 and 1 (for both proportions of length and for area, across
each type of vegetation). The non-transformed data would be expected to
violate the assumptions of ANOVA, so we omit the initial diagnostic
tests. We will again apply Beta regressions.
Below we display the Beta regression model summaries for all
vegetation categories (where present), both length and area proportions.
We omit the diagnostic plots from the display, but when you run the code
for your data, you should examine the plots.
##
##
##
## Model Summary for veg_proportional_length in subveg_result dataset:
##
## Call:
## betareg(formula = response_adjusted ~ site * Time_Category, data = filtered_data)
##
## Quantile residuals:
## Min 1Q Median 3Q Max
## -2.3441 -0.3019 -0.3019 0.4249 0.9525
##
## Coefficients (mean model with logit link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.594e+00 6.142e-01 -2.596 0.00944
## siteHatchery Channel 2.766e+00 8.791e-01 3.146 0.00166
## Time_CategoryBefore -8.473e-17 6.483e-01 0.000 1.00000
## siteHatchery Channel:Time_CategoryBefore -3.269e-01 9.353e-01 -0.350 0.72668
##
## (Intercept) **
## siteHatchery Channel **
## Time_CategoryBefore
## siteHatchery Channel:Time_CategoryBefore
##
## Phi coefficients (precision model with identity link):
## Estimate Std. Error z value Pr(>|z|)
## (phi) 0.7401 0.1778 4.162 3.16e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Type of estimator: ML (maximum likelihood)
## Log-likelihood: 113.4 on 5 Df
## Pseudo R-squared: 0.7103
## Number of iterations: 22 (BFGS) + 2 (Fisher scoring)
##
##
##
## Model Summary for veg_proportional_area in subveg_result dataset:
##
## Call:
## betareg(formula = response_adjusted ~ site * Time_Category, data = filtered_data)
##
## Quantile residuals:
## Min 1Q Median 3Q Max
## -2.3905 -0.3036 -0.3036 0.3115 1.0964
##
## Coefficients (mean model with logit link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.661e+00 6.087e-01 -2.729 0.00635
## siteHatchery Channel 2.498e+00 8.694e-01 2.873 0.00407
## Time_CategoryBefore 2.271e-16 6.425e-01 0.000 1.00000
## siteHatchery Channel:Time_CategoryBefore -7.093e-02 9.408e-01 -0.075 0.93990
##
## (Intercept) **
## siteHatchery Channel **
## Time_CategoryBefore
## siteHatchery Channel:Time_CategoryBefore
##
## Phi coefficients (precision model with identity link):
## Estimate Std. Error z value Pr(>|z|)
## (phi) 0.8011 0.1898 4.22 2.44e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Type of estimator: ML (maximum likelihood)
## Log-likelihood: 103.4 on 5 Df
## Pseudo R-squared: 0.6998
## Number of iterations: 27 (BFGS) + 2 (Fisher scoring)
##
## Warning: optimization failed to converge for veg_proportional_length in emergveg_result dataset
##
##
##
## No model convergence for veg_proportional_length in emergveg_result
##
## Warning: optimization failed to converge for veg_proportional_area in emergveg_result dataset
##
##
##
## No model convergence for veg_proportional_area in emergveg_result
##
##
##
## Model Summary for veg_proportional_length in floatveg_result dataset:
##
## Call:
## betareg(formula = response_adjusted ~ site * Time_Category, data = filtered_data)
##
## Quantile residuals:
## Min 1Q Median 3Q Max
## -1.1733 -0.5225 -0.3722 0.0608 1.9359
##
## Coefficients (mean model with logit link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.96714 0.59286 -3.318 0.000907
## siteHatchery Channel 0.64810 0.74930 0.865 0.387073
## Time_CategoryBefore -0.16239 0.61162 -0.266 0.790619
## siteHatchery Channel:Time_CategoryBefore 0.06658 0.87227 0.076 0.939159
##
## (Intercept) ***
## siteHatchery Channel
## Time_CategoryBefore
## siteHatchery Channel:Time_CategoryBefore
##
## Phi coefficients (precision model with identity link):
## Estimate Std. Error z value Pr(>|z|)
## (phi) 1.5015 0.4167 3.603 0.000314 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Type of estimator: ML (maximum likelihood)
## Log-likelihood: 91.44 on 5 Df
## Pseudo R-squared: 0.2478
## Number of iterations: 21 (BFGS) + 1 (Fisher scoring)
##
##
##
## Model Summary for veg_proportional_area in floatveg_result dataset:
##
## Call:
## betareg(formula = response_adjusted ~ site * Time_Category, data = filtered_data)
##
## Quantile residuals:
## Min 1Q Median 3Q Max
## -0.9762 -0.6076 -0.3915 -0.2771 2.7722
##
## Coefficients (mean model with logit link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -3.0740 0.5594 -5.495 3.9e-08
## siteHatchery Channel 0.3284 0.6659 0.493 0.622
## Time_CategoryBefore -0.2105 0.5587 -0.377 0.706
## siteHatchery Channel:Time_CategoryBefore 0.1576 0.7767 0.203 0.839
##
## (Intercept) ***
## siteHatchery Channel
## Time_CategoryBefore
## siteHatchery Channel:Time_CategoryBefore
##
## Phi coefficients (precision model with identity link):
## Estimate Std. Error z value Pr(>|z|)
## (phi) 6.103 2.047 2.981 0.00288 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Type of estimator: ML (maximum likelihood)
## Log-likelihood: 109.5 on 5 Df
## Pseudo R-squared: 0.1604
## Number of iterations: 23 (BFGS) + 2 (Fisher scoring)
Here is that basic interpretation assistance from before, but also
remember that there is extra nuance now you are dealing with proportions
of pool length or proportion of pool plan area.
“Optimization failed to converge…” If you see this warning, it
may be that there were 0 values across an entire Site. This should be
fairly easy to interpret without inferential tests.
Quantile residuals measure the difference between the actual data
and predicted values. The median should be close to 0. Also check the
residuals vs fitted plot to ensure there is no clear trend or unusual
outliers
Coefficients (mean model): these are the effects of the
predictors (site, time) on the response variable (fine sediment
proportion in pools). Look for significant p values in the last
column, particularly for the Site_____:Time_Category_____ row, which is
the interaction term (if significant, this means the proportion of fines
in residual pools changed over time differently between
sites).
Phi coefficients: there is a p-value here as well, but this
refers to whether the spread of the data around the mean was an
important feature. If the phi estimate is very high, this means the data
was concentrated around the mean (fines proportion doesn’t fluctuate
much between sites/times). Consider phi of 0.1 to be spread out data, 1
to be moderate, and 10 to be concentrated around the mean.
Pseudo R-squared: this is how much of the variation in fines in
pools can be explained by the site and time variables. Often low in
ecological contexts.
Next up are the promised plots that show the distribution of fines
and aquatics across the reach, which should facilitate
interpretation.
Next Steps
We can now move on to looking at a few more components of habitat
that may be useful to monitor for your project. We will export the
residual pool data we generated in this code for use later on (when
considering habitat unit classifications). This will be exported to your
output folder (which by now, might be a bit busy. If moving files
around, remember that the html files need to be in the same folder as
their similarly-named dependency folders).
References
Clark, C., Roni, P. and Burgess, S., 2019. Response of juvenile
salmonids to large wood placement in Columbia River tributaries.
Hydrobiologia, 842(1), pp.173-190.
Geissinger, E.A., Khoo, C.L., Richmond, I.C., Faulkner, S.J. and
Schneider, D.C., 2022. A case for beta regression in the natural
sciences. Ecosphere, 13(2), p.e3940.
Kaufmann, P.R., Levine, P., Peck, D.V., Robison, E.G. and Seeliger,
C., 1999. Quantifying physical habitat in wadeable streams (p. 149).
USEPA [National Health and Environmental Effects Research Laboratory,
Western Ecology Division].
Lisle, T.E., 1986. Effects of woody debris on anadromous salmonid
habitat, Prince of Wales Island, southeast Alaska. North American
Journal of Fisheries Management, 6(4), pp.538-550.
Lisle, T.E., 1987. Using” residual depths” to monitor pool depths
independently of discharge. Res. Note PSW-RN-394. Berkeley, CA: US
Department of Agriculture, Forest Service, Pacific Southwest Forest and
Range Experiment Station. 4 p, 394.
Mossop, B. and Bradford, M.J., 2006. Using thalweg profiling to
assess and monitor juvenile salmon (Oncorhynchus spp.) habitat in small
streams. Canadian Journal of Fisheries and Aquatic Sciences, 63(7),
pp.1515-1525.
Robison, E.G., 1998. Reach scale sampling metrics and longitudinal
pattern adjustment of small streams. PhD Thesis. Oregon State
University.
Stack, W.R., 1988. Factors influencing pool morphology in Oregon
coastal streams. MSc Thesis. Oregon State University
LS0tDQp0aXRsZTogIkxvbmdpdHVkaW5hbCBTdXJ2ZXkgMyBSZXNpZHVhbCBQb29scyINCmF1dGhvcjogIk9saXZlciBGcmFua2xpbiAmIE5pY2NpIFphcmdhcnBvdXIiDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9OSwgZWNobyA9IFRSVUUpDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoInBhY21hbiIsIHF1aWV0bHkgPSBUUlVFKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJwYWNtYW4iKX0NCnBhY21hbjo6cF9sb2FkKERULCB0aWR5dmVyc2UsIGRwbHlyLCB0aWR5ciwgZ2dwbG90Miwga25pdHIsIGthYmxlRXh0cmEsIGdyaWRFeHRyYSwgY293cGxvdCwgY2FyLCBtb21lbnRzLCBwbG90bHksIGh0bWx0b29scywgaHRtbHdpZGdldHMsIHRpYmJsZSwgYmV0YXJlZywgdXBkYXRlPUYpDQpgYGANCg0KYGBge3IgZXhwb3J0IGZ1bmN0aW9ucyBhbmQgZm9sZGVyLCBlY2hvID0gRkFMU0V9DQojIGZ1bmN0aW9ucyB0byB1c2UgZm9yIGV4cG9ydGluZyByZXN1bHRzIHRvIG91dHB1dF9mb2xkZXIgKHdoaWNoIGlzIHByb21wdGVkIGluIFIgd2hlbiBub3QgaW4gUiBlbnZpcm9ubWVudCkNCg0KI2V4cG9ydCBmaWd1cmUgKHBkZiBmb3Igc3RhdGljIGdncGxvdCBwbG90cywgaHRtbCBmb3IgaW50ZXJhY3RpdmUgcGxvdGx5IHBsb3RzKQ0KZXhwb3J0X3Bsb3QgPC0gZnVuY3Rpb24ocGxvdCwgZmlsZW5hbWUpIHsNCiAgaWYgKGluaGVyaXRzKHBsb3QsICJnZ3Bsb3QiKSkgew0KICAgICMgRXhwb3J0IGdncGxvdCBhcyBQREYNCiAgICBnZ3NhdmUoDQogICAgICBmaWxlbmFtZSA9IGZpbGUucGF0aChvdXRwdXRfZm9sZGVyLCBmaWxlbmFtZSksDQogICAgICBwbG90ID0gcGxvdCwNCiAgICAgIGRldmljZSA9ICJwZGYiLA0KICAgICAgd2lkdGggPSAxMSwNCiAgICAgIGhlaWdodCA9IDguNQ0KICAgICkNCiAgfSBlbHNlIGlmIChpbmhlcml0cyhwbG90LCAicGxvdGx5IikpIHsNCiAgICAjIEVuc3VyZSB0aGUgZmlsZW5hbWUgaGFzIC5odG1sIGV4dGVuc2lvbg0KICAgIGh0bWxfZmlsZW5hbWUgPC0gZmlsZS5wYXRoKG91dHB1dF9mb2xkZXIsIHN1YigiXFwucGRmJCIsICIuaHRtbCIsIGZpbGVuYW1lKSkNCiAgICAjIEV4cG9ydCBwbG90bHkgYXMgYSAqKnNpbmdsZSBzZWxmLWNvbnRhaW5lZCoqIEhUTUwgZmlsZQ0KICAgIHNhdmVXaWRnZXQoDQogICAgICB3aWRnZXQgPSBwbG90LCANCiAgICAgIGZpbGUgPSBodG1sX2ZpbGVuYW1lLCANCiAgICAgIHNlbGZjb250YWluZWQgPSBUUlVFICAjIA0KICAgICkNCiAgfSBlbHNlIHsNCiAgICBzdG9wKCJVbnN1cHBvcnRlZCBwbG90IHR5cGUuIE9ubHkgZ2dwbG90IGFuZCBwbG90bHkgb2JqZWN0cyBhcmUgc3VwcG9ydGVkLiIpDQogIH0NCn0NCg0KIyBGdW5jdGlvbiB0byBzYXZlIGEgdGFibGUNCmV4cG9ydF90YWJsZSA8LSBmdW5jdGlvbih0YWJsZSwgZmlsZW5hbWUpIHsNCiAgd3JpdGUuY3N2KA0KICAgIHRhYmxlLA0KICAgIGZpbGUgPSBmaWxlLnBhdGgob3V0cHV0X2ZvbGRlciwgZmlsZW5hbWUpLA0KICAgIHJvdy5uYW1lcyA9IEZBTFNFDQogICkNCn0NCg0KIyBGdW5jdGlvbiB0byBzYXZlIHN1bW1hcnkgYXMgdHh0DQpleHBvcnRfc3VtbWFyeSA8LSBmdW5jdGlvbihzdW1tYXJ5X3RleHQsIGZpbGVuYW1lX2Jhc2UpIHsNCiAgIyBFbnN1cmUgc3VtbWFyeV90ZXh0IGlzIGEgY2hhcmFjdGVyIHZlY3RvciAoaXQgc2hvdWxkIGFscmVhZHkgYmUsIGJ1dCBqdXN0IGluIGNhc2UpDQogIHN1bW1hcnlfdGV4dCA8LSBhcy5jaGFyYWN0ZXIoc3VtbWFyeV90ZXh0KQ0KICAgICMgU2F2ZSBhcyAudHh0DQogIHR4dF9wYXRoIDwtIGZpbGUucGF0aChvdXRwdXRfZm9sZGVyLCBwYXN0ZTAoZmlsZW5hbWVfYmFzZSwgIi50eHQiKSkNCiAgd3JpdGVMaW5lcyhzdW1tYXJ5X3RleHQsIGNvbiA9IHR4dF9wYXRoKQ0KfQ0KDQojIEV4YW1wbGVzIG9mIGV4cG9ydGluZyBpbmRpdmlkdWFsIHJlc3VsdHM6DQojIEV4cG9ydCBhIGZpZ3VyZQ0KIyBleHBvcnRfcGxvdChnZ3Bsb3RfcGxvdCwgIlRoYWx3ZWcgV2F0ZXIgRGVwdGggYnkgRGlzdGFuY2UgVXBzdHJlYW0ucGRmIikNCiMgZXhwb3J0X3Bsb3QocGxvdGx5X3Bsb3QsICJUaGFsd2VnIFdhdGVyIERlcHRoIGJ5IERpc3RhbmNlIFVwc3RyZWFtLmh0bWwiKQ0KIyANCiMgIyBFeHBvcnRpbmcgYSB0YWJsZQ0KIyBzdW1tYXJ5X3RhYmxlIDwtIHN1bW1hcnkobXRjYXJzKQ0KIyBleHBvcnRfdGFibGUoYXMuZGF0YS5mcmFtZShzdW1tYXJ5X3RhYmxlKSwgInN1bW1hcnlfdGFibGUuY3N2IikNCiMgDQojIEV4YW1wbGUgb2YgZXhwb3J0aW5nIGEgc3VtbWFyeQ0KIyBzdW1tYXJ5X3RleHQgPC0gY2FwdHVyZS5vdXRwdXQoc3VtbWFyeShtdGNhcnMpKQ0KIyBleHBvcnRfc3VtbWFyeShzdW1tYXJ5X3RleHQsICJzdW1tYXJ5IikNCg0KIyBiZWxvdyBjb2RlIHRvIGNvbmZpcm0gYW4gb3V0cHV0IGZvbGRlciBpcyBhbHJlYWR5IHNwZWNpZmllZCwgT1Igd2lsbCByZXF1ZXN0IGl0IGlzIHNwZWNpZmllZCBpbiBSIChpbnRlcmFjdGl2ZWx5IHZpYSByZWFkbGluZSkNCiMgQlVUIGlmIHlvdSB3YW50IHRvIGtuaXQsIHlvdSB3aWxsIG5lZWQgdG8gc3BlY2lmeSBhIGRlZmF1bHQgbG9jYXRpb24gKHdpdGhpbiB0aGUgJ2Vsc2UnIHRlcm0pDQppZiAoaW50ZXJhY3RpdmUoKSkgew0KICB3aGlsZSAoIWV4aXN0cygib3V0cHV0X2ZvbGRlciIpIHx8ICFkaXIuZXhpc3RzKG91dHB1dF9mb2xkZXIpKSB7DQogICAgb3V0cHV0X2ZvbGRlciA8LSByZWFkbGluZShwcm9tcHQgPSAiU3BlY2lmeSB0aGUgb3V0cHV0IGZvbGRlcjogIikNCiAgICBpZiAoIWRpci5leGlzdHMob3V0cHV0X2ZvbGRlcikpIHsNCiAgICAgIHRyeUNhdGNoKHsNCiAgICAgICAgZGlyLmNyZWF0ZShvdXRwdXRfZm9sZGVyLCByZWN1cnNpdmUgPSBUUlVFKQ0KICAgICAgICBtZXNzYWdlKCJDcmVhdGVkIGZvbGRlcjogIiwgb3V0cHV0X2ZvbGRlcikNCiAgICAgIH0sIGVycm9yID0gZnVuY3Rpb24oZSkgew0KICAgICAgICBtZXNzYWdlKCJJbnZhbGlkIGZvbGRlci4gUGxlYXNlIHRyeSBhZ2Fpbi4iKQ0KICAgICAgICBvdXRwdXRfZm9sZGVyIDwtIE5VTEwNCiAgICAgIH0pDQogICAgfQ0KICB9DQp9IGVsc2Ugew0KICAjIFNwZWNpZnkgYSBkZWZhdWx0IGZvbGRlciBmb3Igbm9uLWludGVyYWN0aXZlIG1vZGUgKGUuZy4sIGtuaXR0aW5nKQ0KICBvdXRwdXRfZm9sZGVyIDwtICJ+L0dpdC9Db3JlIE1vbml0b3Jpbmcvc3RhbmRhcmRpc2VkIHByb3RvY29scy9kYXRhX3RpZGllci9Mb25naXR1ZGluYWwiDQogIGlmICghZGlyLmV4aXN0cyhvdXRwdXRfZm9sZGVyKSkgew0KICAgIGRpci5jcmVhdGUob3V0cHV0X2ZvbGRlciwgcmVjdXJzaXZlID0gVFJVRSkNCiAgICBtZXNzYWdlKCJEZWZhdWx0IG91dHB1dCBmb2xkZXIgY3JlYXRlZDogIiwgb3V0cHV0X2ZvbGRlcikNCiAgfQ0KfQ0KYGBgDQoNCkluIHRoaXMgc2NyaXB0IHdlIGVzdGltYXRlIHJlc2lkdWFsIHBvb2wgY2hhcmFjdGVyaXN0aWNzLiBUaGUgcmVzaWR1YWwgcG9vbCBpcyB0aGUgcG9vbCB0aGF0IHdvdWxkIGZvcm0gaWYgc3RyZWFtZmxvdyB3ZXJlIHRvIGRlY3JlYXNlIHRvIHplcm8uIEl0cyBkZXB0aCBpcyBjaGFyYWN0ZXJpc2VkIGFzIHRoZSBlbGV2YXRpb24gZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBwb29sJ3MgZGVlcGVzdCBwb2ludCBhbmQgdGhlIHBvb2wgb3V0bGV0IC8gcmlmZmxlIGNyZXN0IHRoYXQgY29udHJvbHMgdGhlIGZsb3cgb2Ygd2F0ZXIgb3V0IG9mIHRoZSBwb29sLiBJdCBzZXJ2ZXMgYXMgYSBmbG93LWluZGVwZW5kZW50IG1ldHJpYyBvZiBwb29scyBpbiBhIHN0cmVhbSBhbmQsIHdpdGggc2V2ZXJhbCBhc3N1bXB0aW9ucywgd2UgY2FuIGVzdGltYXRlIHRoZSBkZXB0aHMsIGFyZWFzLCBhbmQgdm9sdW1lcyBvZiByZXNpZHVhbCBwb29scyBiYXNlZCBvbiBvdXIgZmllbGQgZGF0YS4gU2VlIExpc2xlICgxOTg5KSBmb3IgbW9yZSBiYWNrZ3JvdW5kIG9uIHRoZSBjb25jZXB0IG9mIHJlc2lkdWFsIGRlcHRocy4NCg0KV2UgdHJpZWQgdG8gbWFrZSBmaWVsZCBkYXRhIGNvbGxlY3Rpb24gYXMgc2ltcGxlIGFzIHBvc3NpYmxlIGJ5IHJlbHlpbmcgb24gd2F0ZXIgZGVwdGhzIHJhdGhlciB0aGFuIGVsZXZhdGlvbnMgZm9yIG91ciBsb25naXR1ZGluYWwgcHJvZmlsZXMsIHNvIHRoYXQgcGVvcGxlIGNvdWxkIGNvbGxlY3QgZGF0YSB3aXRob3V0IHN1cnZleSBlcXVpcG1lbnQgLSByZWR1Y2luZyB0aGUgY29zdCBhbmQgZXhwZXJ0aXNlIHJlcXVpcmVkLCBhbmQgZmFjaWxpdGF0aW5nIGFzc2Vzc21lbnQgaW4gZGVuc2VseSB2ZWdldGF0ZWQgLyB3b29keSBjb2FzdGFsIHN0cmVhbXMsIGhpZ2hseSBpbmNpc2VkIGNoYW5uZWxzIGV0Yy4gVGhlIHVzZSBvZiBzaW1wbGUgZGVwdGggZGF0YSByZXF1aXJlcyBhIGNvdXBsZSBvZiBleHRyYSBwcm9jZXNzaW5nIHN0ZXBzIGNvbXBhcmVkIHdpdGggdXNpbmcgZWxldmF0aW9uIGRhdGEsIGJ1dCBsdWNraWx5IHNvbWUgcmF0aGVyIGNsZXZlciBpbmRpdmlkdWFscyBoYXZlIGFscmVhZHkgZmlndXJlZCBpdCBvdXQuIA0KDQpUaGUgY29kZSB3ZSB1c2UgaGVyZSBpcyBhZGFwdGVkIGZyb20gdGhlICdSYXBpZCBCZWQgUHJvZmlsZScgYXBwcm9hY2ggZnJvbSBTdGFjayAoMTk4OSksIHdpdGggYWRkaXRpb25hbCBndWlkYW5jZSBmcm9tIEthdWZtYW4gZXQgYWwuICgxOTk5KSwgYW5kIHdlIGFkb3B0IFN0YWNrJ3Mgc2xvcGUgZmFjdG9yLiBUaGUgc2xvcGUgZmFjdG9yIHdhcyBkZXZlbG9wZWQgaW4gY29hc3RhbCBzdHJlYW1zIGJ1dCBoYXMgYmVlbiBhcHBsaWVkIHN1Y2Nlc3NmdWxseSBpbiBhIHZhcmlldHkgb2Ygb3RoZXIgc3lzdGVtcy4gSWYgeW91IGhhdmUgdGhlIHJlc291cmNlcywgdGhlIGFjY3VyYWN5IG9mIHRoZSBzbG9wZSBmYWN0b3IgZm9yIHlvdXIgcGFydGljdWxhciBzeXN0ZW0gY2FuIGJlIHRlc3RlZCBieSBjb21wYXJpbmcgd2F0ZXItZGVwdGgtZGVyaXZlZCB0byBlbGV2YXRpb24tZGVyaXZlZCByZXNpZHVhbCBwb29sIGRhdGEuIEhvd2V2ZXIsIGV2ZW4gaWYgdGhpcyBhc3N1bXB0aW9uIGlzIHVudGVzdGVkIChhcyBpdCB3aWxsIGJlIGluIG1vc3QgY2FzZXMpLCB0aGUgcmVzdWx0aW5nIG1ldHJpY3MgcmVtYWluIHZhbGlkIGZvciBhc3Nlc3NpbmcgY2hhbmdlcyB3aXRoaW4gYSBzeXN0ZW0sIGFzIGxvbmcgYXMgeW91IGRvbid0IGNoYW5nZSB0aGUgc2xvcGUgZmFjdG9yIGJldHdlZW4geWVhcnMgb3IgcmVhY2hlcyBpbiB5b3VyIGNvbXBhcmlzb24uDQoNCiMgRGF0YSBpbXBvcnQNCg0KRmlyc3Qgd2Ugd2lsbCBpbXBvcnQgdGhlIHRpZGllZCBkYXRhZnJhbWUgZ2VuZXJhdGVkIGJ5IHRoZSBEYXRhIFdyYW5nbGluZyBzY3JpcHQsIHdoaWNoIHdhcyBleHBvcnRlZCB0byB5b3VyIG91dHB1dCBmb2xkZXIuIFRoaXMgZmlsZSBoYXMgbG9uZ2l0dWRpbmFsIHRoYWx3ZWcgd2F0ZXIgZGVwdGggZGF0YSB0aGF0IGluY2x1ZGVzIGJvdGggcmVndWxhciBwcmVkZXRlcm1pbmVkIHNwYWNpbmcgYW5kIGFueSAnZXh0cmEnIHBvb2wgb3V0bGV0cyBhbmQgbWF4IHBvb2wgZGVwdGhzIGVuY291bnRlcmVkICgnWFBPJywgJ1hEJykuIFdlIHByb3Bvc2VkIHRoYXQgdGhlICdleHRyYScgbWVhc3VyZW1lbnRzIHdlcmUgdGFrZW4gaW4gdGhlIGZpZWxkLCBpbiBvcmRlciB0byBjYXB0dXJlIHRoZSBkZXB0aCBtaW5pbWEgKHBvdGVudGlhbCBwb29sIG91dGxldHMpIGFuZCBtYXhpbWEgKGRlZXBlc3QgcG9vbCBzZWN0aW9ucykgdGhhdCBtaWdodCBvY2N1ciBiZXR3ZWVuIHJlZ3VsYXIgaW50ZXJ2YWxzLg0KDQpgYGB7ciBpbXBvcnQgZGF0YSwgZWNobz1GQUxTRX0NCmltcG9ydGVkZGF0YSA8LSBmaWxlLnBhdGgob3V0cHV0X2ZvbGRlciwgIkxvbmdfZGF0YWZyYW1lLmNzdiIpDQpkZiA8LSByZWFkLmNzdihpbXBvcnRlZGRhdGEpICANCg0KIyMgaWYgeW91IG5lZWQgdG8gc3BlY2lmeSBhIGRpZmZlcmVudCBsb2NhdGlvbiB0byBpbXBvcnQgZnJvbSwgdXNlIGJlbG93IGNvZGU6DQojIGltcG9ydGVkZGF0YTwtcmVhZC5jc3YoIn4vR2l0L0NvcmUgTW9uaXRvcmluZy9zdGFuZGFyZGlzZWQgcHJvdG9jb2xzL2RhdGFfdGlkaWVyL0xvbmdpdHVkaW5hbC9Mb25nX2RhdGFmcmFtZS5jc3YiKSAjIHNwZWNpZnkgeW91ciBmaWxlIGxvY2F0aW9uICYgbmFtZSBoZXJlDQojIGRmPC1kYXRhLmZyYW1lKGltcG9ydGVkZGF0YSkNCmBgYA0KDQpJbiB0aGlzIGNvZGUgd2Ugd2lsbCByZXF1aXJlIHNvbWUgYWRkaXRpb25hbCBjb25zdGFudHMgdGhhdCB3ZSBhc2sgeW91IHRvIGRlZmluZSBpbiB0aGUgY29kZSBiZWxvdyBiYXNlZCBvbiBkYXRhIHlvdSByZWNvcmRlZCBpbiB0aGUgZmllbGQgKG9yIGFyZSBhYmxlIHRvIGVzdGltYXRlKS4gVGhpcyBpcyBkb25lIGJ5IGNyZWF0aW5nIGEgZGF0YWZyYW1lL3RhYmxlLCBmb3Igd2hpY2ggeW91IG11c3QgZW50ZXIgdGhlIGZvbGxvd2luZzoNCg0KLSBuYW1lcyBvZiBlYWNoIGNoYW5uZWwNCi0gdGhlIHllYXJzIGRhdGEgd2VyZSBjb2xsZWN0ZWQNCi0gdGhlIHN0YW5kYXJkIGludGVydmFsIHNwYWNpbmcgKGluIG1ldHJlcykgZm9yIGVhY2ggcmVhY2ggYW5kIGVhY2ggeWVhcg0KLSB0aGUgYXZlcmFnZSByZWFjaCBzbG9wZSAoMC41ID0gMC41JSwgbm90IDUwJSkgZm9yIGVhY2ggcmVhY2ggYW5kIGVhY2ggeWVhcg0KLSB0aGUgYXZlcmFnZSB3ZXR0ZWQgd2lkdGggZHVyaW5nIGxvdyBmbG93IChpbiBtZXRyZXMpIGZvciBlYWNoIHJlYWNoIGFuZCBlYWNoIHllYXIuDQoNCkVudGVyIHRoaXMgaW5mb3JtYXRpb24gaW4gdGhlIGNvZGUgYmVsb3cuIERhdGEgaXMgZW50ZXJlZCBpbiB2ZWN0b3JzIG9mIGVxdWFsIGxlbmd0aCBhbmQgZm9sbG93aW5nIHRoZSBzYW1lIHNlcXVlbmNlLiBGb3IgZXhhbXBsZSwgaW4gdGhlIGV4aXN0aW5nIGNvZGUsIEhhdGNoZXJ5IENoYW5uZWwgaXMgYXNzb2NpYXRlZCB3aXRoIHNwYWNpbmcgb2YgMSBhbmQgMSwgc2xvcGUgb2YgMSBhbmQgMS4xLCBhbmQgd2V0dGVkIHdpZHRoIG9mIDYuOCBhbmQgNy4wLCBmb3IgMjAyNCBhbmQgMjAyNSByZXNwZWN0aXZlbHkuDQpPbmNlIHlvdSBjcmVhdGUgdGhlIGRhdGFmcmFtZSB3aXRoIHlvdXIgZGF0YSwgY2hlY2sgdGhyb3VnaCB0aGUgdGFibGUgdG8gZW5zdXJlIHRoZXNlIGNvbnN0YW50cyBhcmUgYXNzaWduZWQgdG8gdGhlIGNvcnJlY3QgcmVhY2ggJiB5ZWFyLg0KDQpgYGAge3IgaW5wdXQgY29uc3RhbnRzfQ0KIyBDcmVhdGUgYSBkYXRhIGZyYW1lIHRvIGhvbGQgY29uc3RhbnRzIGZvciBtdWx0aXBsZSBzaXRlcyBhbmQgeWVhcnMuIEVudGVyIHlvdXIgZGF0YSBiZWxvdzoNCmNvbnN0YW50c19kZiA8LSBkYXRhLmZyYW1lKA0KICBTaXRlID0gYygiSGF0Y2hlcnkgQ2hhbm5lbCIsICJIYXRjaGVyeSBDaGFubmVsIiwgIkJyb3Vzc2VhdSBDaGFubmVsIiwgIkJyb3Vzc2VhdSBDaGFubmVsIiksICAjIEVkaXQgLyBBZGQgeW91ciBzaXRlIG5hbWVzDQogIHllYXIgPSBjKDIwMjQsIDIwMjUsIDIwMjQsIDIwMjUpLCAgIyBDb3JyZXNwb25kaW5nIHllYXJzIGZvciBlYWNoIHNpdGUNCiAgc3BhY2luZyA9IGMoMSwgMSwgMSwgMSksICAjIHNwYWNpbmcgdmFsdWVzIGZvciBlYWNoIHNpdGUteWVhciBjb21iaW5hdGlvbg0KICBTbG9wZSA9IGMoMC41LCAwLjYsIDAuNSwgMC41KSwgICAgIyBTbG9wZSB2YWx1ZXMgZm9yIGVhY2ggc2l0ZS15ZWFyIGNvbWJpbmF0aW9uLCBpbiAlDQogIFdldFdpZHRoID0gYyg2LjgsIDcuMCwgNi41LCA3LjEpICAjIEF2ZXJhZ2Ugd2V0dGVkIHdpZHRoIGluIG0sIGZvciBlYWNoIHNpdGUteWVhciBjb21iaW5hdGlvbg0KKQ0KDQojIFZpZXcgdGhlIGNvbnN0YW50cyBkYXRhIGZyYW1lDQpwcmludChjb25zdGFudHNfZGYpDQpgYGANCg0KYGBge3IgY29uc3RhbnQgZXh0cmFjdCBmdW5jdGlvbiwgZWNobyA9IEZBTFNFfQ0KIyBGdW5jdGlvbiB0byBnZXQgY29uc3RhbnRzIGZvciBhIHNwZWNpZmljIFNpdGUgYW5kIHllYXINCmdldF9jb25zdGFudHMgPC0gZnVuY3Rpb24oc2l0ZSwgeWVhcikgew0KICBjb25zdGFudHNfcm93IDwtIGNvbnN0YW50c19kZltjb25zdGFudHNfZGYkU2l0ZSA9PSBzaXRlICYgY29uc3RhbnRzX2RmJHllYXIgPT0geWVhciwgXQ0KICANCiAgaWYgKG5yb3coY29uc3RhbnRzX3JvdykgPT0gMCkgew0KICAgIHN0b3AocGFzdGUoIk5vIGNvbnN0YW50cyBmb3VuZCBmb3IgU2l0ZToiLCBzaXRlLCAieWVhcjoiLCB5ZWFyKSkNCiAgfQ0KICAgIA0KICAjIEV4dHJhY3QgY29uc3RhbnRzDQogIHNwYWNpbmcgPC0gY29uc3RhbnRzX3JvdyRzcGFjaW5nDQogIHNsb3BlIDwtIGNvbnN0YW50c19yb3ckU2xvcGUNCiAgd2V0d2lkdGggPC0gY29uc3RhbnRzX3JvdyRXZXRXaWR0aA0KICANCiAgcmV0dXJuKGxpc3Qoc3BhY2luZyA9IHNwYWNpbmcsIHNsb3BlID0gc2xvcGUsIHdldHdpZHRoID0gd2V0d2lkdGgpKQ0KfQ0KYGBgDQoNCiMgQ3JlYXRpb24gb2YgUmVzaWR1YWwgU3VyZmFjZXMNCg0KYGBge3IgY3JlYXRlIGFydGlmaWNpYWwgbmlja3BvaW50cywgZWNobyA9IEZBTFNFfQ0KIyBBbHRob3VnaCB3ZSByZWNvbW1lbmRlZCBzdGFydGluZyB0aGUgbG9uZ2l0dWRpbmFsIGZpZWxkIHN1cnZleSBkb3duc3RyZWFtIGF0IGEgcG9vbCBvdXRsZXQgLyByaWZmbGUgY3Jlc3QsIHRoaXMgaXMgbm90IGFsd2F5cyBwb3NzaWJsZS4gVGhpcyBjb2RlIGNyZWF0ZXMgYXJ0aWZpY2lhbCBkb3duc3RyZWFtIG5pY2sgcG9pbnRzIHRoYXQgd2lsbCBhbGxvdyB1cyB0byBpbmNsdWRlIGFyZWFzIG9mIHBvb2wgYXQgdGhlIGJvdHRvbSBvZiBvdXIgcmVhY2hlcyB0aGF0IHdlcmUgbm90IGNvbnRhaW5lZCBieSBhbiBvdXRsZXQuDQoNCiMgSWRlbnRpZnkgdW5pcXVlIHNpdGVzIGFuZCB5ZWFycyBpbiB0aGUgZGF0YQ0KdW5pcXVlX3NpdGVzX3llYXJzIDwtIHVuaXF1ZShkZlssIGMoIlNpdGUiLCAieWVhciIpXSkNCg0KIyBJbml0aWFsaXplIGFuIGVtcHR5IGxpc3QgdG8gc3RvcmUgYXJ0aWZpY2lhbCByb3dzDQphcnRpZmljaWFsX3Jvd3MgPC0gbGlzdCgpDQoNCiMgTG9vcCB0aHJvdWdoIGVhY2ggdW5pcXVlIGNvbWJpbmF0aW9uIG9mIFNpdGUgYW5kIHllYXINCmZvciAoaSBpbiAxOm5yb3codW5pcXVlX3NpdGVzX3llYXJzKSkgew0KICBzaXRlIDwtIHVuaXF1ZV9zaXRlc195ZWFycyRTaXRlW2ldDQogIHllYXIgPC0gdW5pcXVlX3NpdGVzX3llYXJzJHllYXJbaV0NCiAgDQogICMgU3Vic2V0IHRoZSBkYXRhIGZvciB0aGUgY3VycmVudCBzaXRlIGFuZCB5ZWFyDQogIHNpdGVfeWVhcl9kYXRhIDwtIHN1YnNldChkZiwgU2l0ZSA9PSBzaXRlICYgeWVhciA9PSB5ZWFyKQ0KICANCiAgIyBDYWxjdWxhdGUgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIFRoYWx3ZWdfRGVwdGhfbSBmb3IgdGhlIGN1cnJlbnQgc3Vic2V0DQogIHRoYWx3ZWdfbWVhbiA8LSBtZWFuKHNpdGVfeWVhcl9kYXRhJFRoYWx3ZWdfRGVwdGhfbSwgbmEucm0gPSBUUlVFKQ0KICB0aGFsd2VnX3NkIDwtIHNkKHNpdGVfeWVhcl9kYXRhJFRoYWx3ZWdfRGVwdGhfbSwgbmEucm0gPSBUUlVFKQ0KICANCiMgUmV0cmlldmUgdGhlIGNvcnJlY3Qgc3BhY2luZyB2YWx1ZSBmcm9tIGNvbnN0YW50c19kZiBmb3IgdGhpcyBzaXRlIGFuZCB5ZWFyDQpzcGFjaW5nX3ZhbHVlIDwtIGNvbnN0YW50c19kZiAlPiUNCiAgZmlsdGVyKFNpdGUgPT0gc2l0ZSAmIHllYXIgPT0geWVhcikgJT4lDQogIGRpc3RpbmN0KHNwYWNpbmcpICU+JSAgIyBFbnN1cmUgdW5pcXVlIHNwYWNpbmcgdmFsdWVzDQogIHB1bGwoc3BhY2luZykgICMgRXh0cmFjdCB0aGUgc3BhY2luZyB2YWx1ZSBmb3IgdGhlIGN1cnJlbnQgc2l0ZS15ZWFyIGNvbWJpbmF0aW9uDQoNCiMgQ2hlY2sgaWYgdGhlIHNwYWNpbmcgdmFsdWUgaXMgdmFsaWQgKGxlbmd0aCBzaG91bGQgYmUgZXhhY3RseSAxKS4gVGhpcyBpcyBoZXJlIGJlY2F1c2Ugd2UgZW5jb3VudGVyZWQgaXNzdWVzIHdpdGggZHVwbGljYXRlczsgcmV0YWluaW5nIGl0IGluIGNhc2UgeW91IHJ1biBpbnRvIGEgc2ltaWxhciBlcnJvcg0KaWYgKGxlbmd0aChzcGFjaW5nX3ZhbHVlKSAhPSAxKSB7DQogIHN0b3AocGFzdGUoIlRoZXJlIGlzIGFuIGlzc3VlIHdpdGggdGhlIHNwYWNpbmcgdmFsdWUgZm9yIFNpdGU6Iiwgc2l0ZSwgImFuZCBZZWFyOiIsIHllYXIsIA0KICAgICAgICAgICAgICItIGV4cGVjdGVkIG9uZSB2YWx1ZSBidXQgZm91bmQiLCBsZW5ndGgoc3BhY2luZ192YWx1ZSksICJ2YWx1ZXMiKSkNCn0NCiAgIyBDcmVhdGUgYSBuZXcgcm93IHdpdGggTkEgdmFsdWVzIGZvciBhbGwgY29sdW1ucw0KICBuZXdfcm93IDwtIHNpdGVfeWVhcl9kYXRhWzEsIF0gICMgVXNlIHRoZSBmaXJzdCByb3cgYXMgYSB0ZW1wbGF0ZQ0KICBuZXdfcm93W10gPC0gTkEgICMgUmVwbGFjZSBhbGwgdmFsdWVzIHdpdGggTkENCiAgDQogICMgUHJvdmlkZSB2YWx1ZXMgZm9yIHRoZSBuaWNrIHBvaW50IG5ldyByb3csIG9ubHkgd2hlcmUgdmFsdWVzIGFyZSBuZWVkZWQNCiAgbmV3X3JvdyRMb2NhdGlvbl9Db2RlIDwtICJuaWNrcHRzIg0KICBuZXdfcm93JFRoYWx3ZWdfRGVwdGhfbSA8LSB0aGFsd2VnX21lYW4gLSB0aGFsd2VnX3NkDQogIG5ld19yb3ckZGlzdGFuY2UgPC0gLTEgKiBzcGFjaW5nX3ZhbHVlICAjIFVzZSB0aGUgc3BhY2luZyB2YWx1ZSBmb3IgZGlzdGFuY2UsIGFzc2lnbiBpdCBuZWdhdGl2ZSB0byBsYXRlciBmaWx0ZXIgb3V0DQogIG5ld19yb3ckRmluZXMgPC0gIk4iICAjIERlZmluZSB0aGVzZSByb3dzIHRvIHBsb3QgdGhlbSBwcm9wZXJseSBsYXRlcg0KICBuZXdfcm93JGZsb2F0dmVnIDwtIDAgDQogIG5ld19yb3ckc3VidmVnIDwtIDANCiAgbmV3X3JvdyRlbWVyZ3ZlZyA8LSAwDQogIG5ld19yb3ckU2l0ZSA8LSBzaXRlDQogIG5ld19yb3ckeWVhciA8LSB5ZWFyICANCiAgDQogICMgQWRkIHRoZSBuZXcgcm93IHRvIHRoZSBsaXN0IG9mIGFydGlmaWNpYWwgcm93cw0KICBhcnRpZmljaWFsX3Jvd3NbW2ldXSA8LSBuZXdfcm93DQp9DQoNCiMgQ29tYmluZSBhbGwgYXJ0aWZpY2lhbCByb3dzIGFuZCB0aGUgb3JpZ2luYWwgZGF0YQ0KZGZfYXJ0aWZpY2lhbCA8LSBkby5jYWxsKHJiaW5kLCBhcnRpZmljaWFsX3Jvd3MpDQpkZiA8LSByYmluZChkZl9hcnRpZmljaWFsLCBkZikNCmBgYA0KVGhlIHJlc2lkdWFsIHN1cmZhY2UgaXMgdGhlIHdhdGVyIHN1cmZhY2UgYXQgdGhlIHBvaW50IHdoZW4gc3RyZWFtZmxvdyBhcHByb2FjaGVzIHplcm8sIGFuZCByZXNpZHVhbCBkZXB0aCBpcyB0aGUgdmVydGljYWwgZGlzdGFuY2UgYmV0d2VlbiB0aGUgcmVzaWR1YWwgc3VyZmFjZSBhbmQgdGhlIHN0cmVhbSBiZWQuIEFzIHN1Y2gsIHdoZW4gd2UgZXN0aW1hdGUgcmVzaWR1YWwgcG9vbHMgYW5kIHJlc2lkdWFsIGRlcHRocywgdGhlc2UgYXJlIGZlYXR1cmVzIHRoYXQgYXJlIGluZGVwZW5kZW50IG9mIGZsb3cgY29uZGl0aW9ucyBhdCB0aGUgdGltZSBvZiB0aGUgZmllbGQgc3VydmV5LiBXaGlsZSB0aGV5IG1pZ2h0IGJlIHJlcHJlc2VudGF0aXZlIG9mIGFjdHVhbCBwb29sIGNvbmRpdGlvbnMgZHVyaW5nIHRpbWVzIG9mIHZlcnkgbG93IGZsb3csIHRoZWlyIHZhbHVlIGxpZXMgd2l0aCB0aGUgYWJpbGl0eSB0byBtYWtlIGNvbXBhcmlzb25zIG9mIHBvb2wgaGFiaXRhdCBhbW9uZyB5ZWFycyBhbmQvb3IgcmVhY2hlcyB3aXRob3V0IHF1YW50aWZ5aW5nIGFuZCBjb250cm9sbGluZyBmb3IgdmFyaWFibGUgZmxvdyBjb25kaXRpb25zLiANCg0KT3VyIGNvZGUgdXNlcyB0aGUgc2VxdWVuY2Ugb2YgdGhhbHdlZyBkZXB0aCBtZWFzdXJlbWVudHMgdG8gaWRlbnRpZnkgcG90ZW50aWFsIHBvb2wgb3V0bGV0cyBpbiB0aGUgc2FtcGxlZCByZWFjaCwgYW5kIGVzdGltYXRlcyByZXNpZHVhbCBkZXB0aHMgYXQgZWFjaCBtZWFzdXJlbWVudCBsb2NhdGlvbiBiYXNlZCBvbiBhIHByb2plY3RlZCByZXNpZHVhbCBzdXJmYWNlIHRoYXQgZXh0ZW5kcyB1cHN0cmVhbSBmcm9tIGVhY2ggcG9vbCBvdXRsZXQuIFRoZSByZXNpZHVhbCBzdXJmYWNlIGlzIHByb2plY3RlZCB1c2luZyB0aGUgZXhwZWN0ZWQgcG9vbCB3YXRlciBzdXJmYWNlIHNsb3BlICh3aGljaCBpcyBlc3RpbWF0ZWQgdXNpbmcgU3RhY2sncyBlbXBpcmljYWwgZXF1YXRpb24sIGluY29ycG9yYXRpbmcgdGhlIGF2ZXJhZ2UgcmVhY2ggc2xvcGUgdGhhdCB5b3UgZW50ZXJlZCBhcyBhIGNvbnN0YW50KS4gDQoNCkl0IGlzIGltcG9ydGFudCB0byBub3RlIHRoYXQgd2hlbiB3ZSBpZGVudGlmeSBwb29sIG91dGxldHMgb3IgcmlmZmxlIGNyZXN0cyAoZWl0aGVyIGluIHRoZSBmaWVsZCBvciB1c2luZyB0aGlzIGNvZGUpLCB3ZSB1c3VhbGx5IGJhc2UgdGhpcyBkZXRlcm1pbmF0aW9uIG9uIHRoZSBiZWQgZWxldmF0aW9uIGFuZC9vciB3YXRlciBkZXB0aCBhdCB0aGUgY3VycmVudCBsb2NhdGlvbiBjb21wYXJlZCB3aXRoIHRoZSBhcmVhcyBpbW1lZGlhdGVseSBhZGphY2VudC4gSG93ZXZlciwgYSBwb3RlbnRpYWwgcG9vbCBvdXRsZXQgd2lsbCBub3QgJ2JlaGF2ZScgYXMgYSBwb29sIG91dGxldCB1bmRlciBhbGwgZmxvdyBjb25kaXRpb25zOiBpdCBjb3VsZCBiZSBoaWdoIGFuZCBkcnkgdW5kZXIgdmVyeSBsb3cgZmxvdyBjb25kaXRpb25zLCBvciBpdCBjb3VsZCBpdHNlbGYgYmUgd2l0aGluIGEgcG9vbCBkdWUgdG8gdGhlIGJhY2t3YXRlcmluZyBlZmZlY3RzIG9mIGEgaGlnaGVyLWVsZXZhdGlvbiBwb29sIG91dGxldCBkb3duc3RyZWFtLiBGcm9tIGhlcmUgb253YXJkLCB3ZSB3aWxsIHVzZSB0aGUgdGVybSAqJ2xvY2FsIGRlcHRoIG1pbmltYScqICgnTERNJyBpbiBjb2RlKSB0byByZWZlciB0byBsb2NhdGlvbnMgdGhhdCBoYXZlIHRoZSBwb3RlbnRpYWwgdG8gYmUgcG9vbCBvdXRsZXRzIC0gdGhhdCBpcywgdGhleSBhcmUgbGVzcyBkZWVwIHRoYW4gYXJlYXMgaW1tZWRpYXRlbHkgZG93bnN0cmVhbSBhbmQgdXBzdHJlYW0sIGFjY291bnRpbmcgZm9yIHRoZSBzbG9wZSBvZiB0aGUgc3RyZWFtLiBXZSB3aWxsIHJlc2VydmUgdGhlIHRlcm0gJ3Bvb2wgb3V0bGV0JyBmb3IgY2FzZXMgd2hlbiBsb2NhbCBkZXB0aCBtaW5pbWEgd291bGQgYmUgZXhwZWN0ZWQgdG8gYWN0dWFsbHkgYmFja3dhdGVyIGEgcG9vbCB1bmRlciBmbG93IGNvbmRpdGlvbnMgYXBwcm9hY2hpbmcgemVyby4gDQoNCkF0IHRoaXMgcG9pbnQgb3VyIGNvZGUgd2lsbCBnZW5lcmF0ZSBhIG5ldyBkYXRhZnJhbWUgKHJlc2lkdWFscy5kZikgd2l0aCB0aGUgbG9jYWwgZGVwdGggbWluaW1hIGlkZW50aWZpZWQgYW5kIHRoZSByZXNpZHVhbCBzdXJmYWNlIHByb2plY3RlZC4gSWYgeW91IGFyZSBpbnRlcmVzdGVkIGluIGhvdyB0aGlzIGlzIGRvbmUsIGNoZWNrIG91dCB0aGUgUiBjb2RlLiBGb3IgZXZlcnlvbmUgZWxzZSwgaGVyZSBhcmUgc29tZSBmaXNoOiANCg0K8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8g8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8g8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8g8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8g8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8g8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8g8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8g8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8g8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8NCg0KYGBge3IgcmVzaWR1YWwgc3VyZmFjZXMgYW5kIGRlcHRocywgZWNobyA9IEZBTFNFfQ0KIyBOQjogd2UgaGF2ZSBtb2RpZmllZCB0aGUgYXBwcm9hY2ggdXNlZCBpbiBLYXVmbWFuIGV0IGFsLiAxOTk5IHRvIGFjY291bnQgZm9yIHRoZSBmYWN0IHRoYXQgd2UgbWVhc3VyZWQgdGhlIG1heGltdW0gZGVwdGggb2YgcG9vbHMNCiMgYW5kIHRoZSBkZXB0aCBvZiBwb29sIG91dGxldHMgKndoZXJldmVyIHdlIGVuY291bnRlcmVkIHRoZW0qIGFsb25nIG91ciBzYW1wbGVkIHJlYWNoIChub3QganVzdCBhdCBwcmVkZXRlcm1pbmVkIGludGVydmFscykuDQojIEFzIHN1Y2gsIHdlIGJhc2Ugb3VyIHJlc2lkdWFsIHBvb2wgY2FsY3VsYXRpb25zIG9uIGRpZmZlcmVuY2VzIGluIHRoZSBkaXN0YW5jZSBjb2x1bW4gdGhhdCB3ZSBwcmV2aW91c2x5IGNvbXB1dGVkLg0KDQojIE1lcmdlIGNvbnN0YW50c19kZiB3aXRoIGRmIHRvIGFkZCB0aGUgc2xvcGUgYW5kIHdldHdpZHRoIHZhbHVlcw0KZGYgPC0gZGYgJT4lDQogIGxlZnRfam9pbihjb25zdGFudHNfZGYsIGJ5ID0gYygiU2l0ZSIsICJ5ZWFyIikpDQoNCiMgUmVzaWR1YWwgZGVwdGggZnVuY3Rpb24gdG8gY3JlYXRlIHJlc2lkdWFscy5kZiAoaW5zdGVhZCBvZiBtb2RpZnlpbmcgZGYpDQpjYWxjdWxhdGVfcmVzaWR1YWxfZGVwdGhzIDwtIGZ1bmN0aW9uKGRmKSB7DQogICMgRW5zdXJlIHRoZSBkYXRhZnJhbWUgaXMgc29ydGVkIGJ5IGRpc3RhbmNlLCBzbyB0aGF0IGNhbGN1bGF0aW9ucyBwcm9ncmVzcyBpbiBjb3JyZWN0IG9yZGVyDQogIGRmIDwtIGRmW29yZGVyKGRmJGRpc3RhbmNlKSwgXQ0KICANCiAgIyBJbml0aWFsaXplIHJlcXVpcmVkIGNvbHVtbnMNCiAgcmVzaWR1YWxzLmRmIDwtIGRmICMgU3RhcnQgd2l0aCBhIGNvcHkgb2YgdGhlIGlucHV0IGRhdGFmcmFtZQ0KICByZXNpZHVhbHMuZGYkcmVzaWR1YWxfc3VyZmFjZSA8LSBOQQ0KICByZXNpZHVhbHMuZGYkcmVzaWR1YWxfZGVwdGggPC0gTkENCiAgcmVzaWR1YWxzLmRmJHJlc2lkdWFsX3dpZHRoIDwtIE5BDQogIHJlc2lkdWFscy5kZiRMRE1faWQgPC0gTkENCiAgDQogICMgRGVmaW5lIGNvbnN0YW50cyAoc2xvcGUgZmFjdG9yIGFkanVzdG1lbnQgZm9yIHBlcmNlbnRhZ2UuIEZvcm11bGEgZnJvbSBTdGFjayAxOTg5KQ0KICBzbG9wZV9mYWN0b3IgPC0gKDAuMTIgKyAwLjI1ICogcmVzaWR1YWxzLmRmJFNsb3BlWzFdKSAvIDEwMA0KICB3ZXR3aWR0aCA8LSByZXNpZHVhbHMuZGYkV2V0V2lkdGhbMV0NCiAgDQogICMgSWRlbnRpZnkgbG9jYWwgZGVwdGggbWluaW1hIChyaWZmbGUgY3Jlc3RzL2NvbnRyb2wgcG9pbnRzL3Bvb2wgb3V0bGV0cykNCiAgTERNX2lkIDwtIDAgDQogIGxhc3RfcmVzaWR1YWxfc3VyZmFjZSA8LSBOQQ0KICBsYXN0X3Jlc2lkdWFsX2luZGV4IDwtIDAuMQ0KICANCiAgIyBIYW5kbGUgYXJ0aWZpY2lhbCBvdXRsZXQgKG5lZ2F0aXZlIGRpc3RhbmNlIHZhbHVlKQ0KICBpZiAocmVzaWR1YWxzLmRmJGRpc3RhbmNlWzFdIDwgMCkgew0KICAgIExETV9pZCA8LSBMRE1faWQgKyAxDQogICAgZG93bnN0cmVhbV9kZXB0aCA8LSByZXNpZHVhbHMuZGYkVGhhbHdlZ19EZXB0aF9tWzFdDQogICAgZG93bnN0cmVhbV9pbmRleCA8LSAxDQogICAgcmVzaWR1YWxzLmRmJExETV9pZFsxXSA8LSBMRE1faWQNCiAgICANCiAgICAjIFByb2plY3QgcmVzaWR1YWwgc3VyZmFjZSB1cHN0cmVhbSBmcm9tIHRoZSBhcnRpZmljaWFsIG91dGxldA0KICAgIGZvciAoZSBpbiAxOm5yb3cocmVzaWR1YWxzLmRmKSkgew0KICAgICAgc3BhY2luZ19jdXJyZW50IDwtIHJlc2lkdWFscy5kZiRkaXN0YW5jZVtlXSAtIHJlc2lkdWFscy5kZiRkaXN0YW5jZVsxXQ0KICAgICAgcmVzaWR1YWxfc3VyZmFjZSA8LSBkb3duc3RyZWFtX2RlcHRoICsgc2xvcGVfZmFjdG9yICogc3BhY2luZ19jdXJyZW50DQoNCiAgICAgIGlmICghaXMubmEocmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbVtlXSkpIHsNCiAgICAgICAgaWYgKHJlc2lkdWFsX3N1cmZhY2UgPD0gcmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbVtlXSkgew0KICAgICAgICAgIHJlc2lkdWFscy5kZiRyZXNpZHVhbF9zdXJmYWNlW2VdIDwtIHJlc2lkdWFsX3N1cmZhY2UNCiAgICAgICAgICByZXNpZHVhbHMuZGYkcmVzaWR1YWxfZGVwdGhbZV0gPC0gcmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbVtlXSAtIHJlc2lkdWFsX3N1cmZhY2UNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICByZXNpZHVhbHMuZGYkcmVzaWR1YWxfc3VyZmFjZVtlXSA8LSByZXNpZHVhbHMuZGYkVGhhbHdlZ19EZXB0aF9tW2VdDQogICAgICAgICAgcmVzaWR1YWxzLmRmJHJlc2lkdWFsX2RlcHRoW2VdIDwtIDANCiAgICAgICAgICBicmVhaw0KICAgICAgICB9DQogICAgICB9IGVsc2Ugew0KICAgICAgICBicmVhaw0KICAgICAgfQ0KICAgIH0NCiAgfQ0KDQogICMgSXRlcmF0ZSB0aHJvdWdoIHRoZSByZXN0IG9mIHRoZSByb3dzIHRvIGlkZW50aWZ5IGxvY2FsIGRlcHRoIG1pbmltYQ0KICBmb3IgKGIgaW4gMjoobnJvdyhyZXNpZHVhbHMuZGYpIC0gMSkpIHsNCiAgICBzcGFjaW5nX3ByZXYgPC0gcmVzaWR1YWxzLmRmJGRpc3RhbmNlW2JdIC0gcmVzaWR1YWxzLmRmJGRpc3RhbmNlW2IgLSAxXQ0KICAgIHNwYWNpbmdfbmV4dCA8LSByZXNpZHVhbHMuZGYkZGlzdGFuY2VbYiArIDFdIC0gcmVzaWR1YWxzLmRmJGRpc3RhbmNlW2JdDQogICAgDQogICAgIyBDaGVjayBpZiB0aGUgY3VycmVudCBwb2ludCBpcyBhIGxvY2FsIGRlcHRoIG1pbmltdW0NCiAgICBpZiAoKHJlc2lkdWFscy5kZiRUaGFsd2VnX0RlcHRoX21bYl0gPD0gKHJlc2lkdWFscy5kZiRUaGFsd2VnX0RlcHRoX21bYiAtIDFdICsgc2xvcGVfZmFjdG9yICogc3BhY2luZ19wcmV2KSAmJg0KICAgICAgICAgKHJlc2lkdWFscy5kZiRUaGFsd2VnX0RlcHRoX21bYl0gKyBzbG9wZV9mYWN0b3IgKiBzcGFjaW5nX25leHQpIDwgcmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbVtiICsgMV0pIHx8DQogICAgICAgIHJlc2lkdWFscy5kZiRkaXN0YW5jZVtiXSA8IDApIHsNCiAgICAgIA0KICAgICAgTERNX2lkIDwtIExETV9pZCArIDENCiAgICAgIGRvd25zdHJlYW1fZGVwdGggPC0gcmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbVtiXQ0KICAgICAgZG93bnN0cmVhbV9pbmRleCA8LSBiDQogICAgICByZXNpZHVhbHMuZGYkTERNX2lkW2JdIDwtIExETV9pZA0KDQogICAgICBpZiAoaXMubmEobGFzdF9yZXNpZHVhbF9zdXJmYWNlKSB8fCByZXNpZHVhbHMuZGYkZGlzdGFuY2VbYl0gPiByZXNpZHVhbHMuZGYkZGlzdGFuY2VbbGFzdF9yZXNpZHVhbF9pbmRleF0pIHsNCiAgICAgICAgaWYgKGlzLm5hKGxhc3RfcmVzaWR1YWxfc3VyZmFjZSkpIHsNCiAgICAgICAgICBwcm9qZWN0ZWRfcmVzaWR1YWxfc3VyZmFjZSA8LSByZXNpZHVhbHMuZGYkcmVzaWR1YWxfc3VyZmFjZVtiIC0gMV0gKyBzbG9wZV9mYWN0b3IgKiAocmVzaWR1YWxzLmRmJGRpc3RhbmNlW2JdIC0gcmVzaWR1YWxzLmRmJGRpc3RhbmNlW2IgLSAxXSkNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICBwcm9qZWN0ZWRfcmVzaWR1YWxfc3VyZmFjZSA8LSBsYXN0X3Jlc2lkdWFsX3N1cmZhY2UgKyBzbG9wZV9mYWN0b3IgKiAocmVzaWR1YWxzLmRmJGRpc3RhbmNlW2JdIC0gcmVzaWR1YWxzLmRmJGRpc3RhbmNlW2xhc3RfcmVzaWR1YWxfaW5kZXhdKQ0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKGRvd25zdHJlYW1fZGVwdGggPD0gcHJvamVjdGVkX3Jlc2lkdWFsX3N1cmZhY2UpIHsNCiAgICAgICAgICBsYXN0X3Jlc2lkdWFsX3N1cmZhY2UgPC0gZG93bnN0cmVhbV9kZXB0aA0KICAgICAgICAgIGxhc3RfcmVzaWR1YWxfaW5kZXggPC0gYg0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgIG5leHQNCiAgICAgICAgfQ0KICAgICAgfQ0KICAgICAgDQogICAgICBmb3IgKGUgaW4gKGxhc3RfcmVzaWR1YWxfaW5kZXggKyAxKTpucm93KHJlc2lkdWFscy5kZikpIHsNCiAgICAgICAgc3BhY2luZ19jdXJyZW50IDwtIHJlc2lkdWFscy5kZiRkaXN0YW5jZVtlXSAtIHJlc2lkdWFscy5kZiRkaXN0YW5jZVtsYXN0X3Jlc2lkdWFsX2luZGV4XQ0KICAgICAgICByZXNpZHVhbF9zdXJmYWNlIDwtIGxhc3RfcmVzaWR1YWxfc3VyZmFjZSArIHNsb3BlX2ZhY3RvciAqIHNwYWNpbmdfY3VycmVudA0KDQogICAgICAgIGlmICghaXMubmEocmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbVtlXSkgJiYgIWlzLm5hKHJlc2lkdWFsX3N1cmZhY2UpKSB7DQogICAgICAgICAgaWYgKHJlc2lkdWFsX3N1cmZhY2UgPiByZXNpZHVhbHMuZGYkVGhhbHdlZ19EZXB0aF9tW2VdKSB7DQogICAgICAgICAgICByZXNpZHVhbHMuZGYkcmVzaWR1YWxfc3VyZmFjZVtlXSA8LSByZXNpZHVhbHMuZGYkVGhhbHdlZ19EZXB0aF9tW2VdDQogICAgICAgICAgICByZXNpZHVhbHMuZGYkcmVzaWR1YWxfZGVwdGhbZV0gPC0gMA0KICAgICAgICAgICAgbGFzdF9yZXNpZHVhbF9zdXJmYWNlIDwtIHJlc2lkdWFscy5kZiRUaGFsd2VnX0RlcHRoX21bZV0NCiAgICAgICAgICAgIGxhc3RfcmVzaWR1YWxfaW5kZXggPC0gZQ0KICAgICAgICAgICAgYnJlYWsNCiAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgcmVzaWR1YWxzLmRmJHJlc2lkdWFsX3N1cmZhY2VbZV0gPC0gcmVzaWR1YWxfc3VyZmFjZQ0KICAgICAgICAgICAgcmVzaWR1YWxfZGVwdGggPC0gcmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbVtlXSAtIHJlc2lkdWFsX3N1cmZhY2UNCiAgICAgICAgICAgIHJlc2lkdWFscy5kZiRyZXNpZHVhbF9kZXB0aFtlXSA8LSBpZmVsc2UocmVzaWR1YWxfZGVwdGggPiAwLCByZXNpZHVhbF9kZXB0aCwgMCkNCiAgICAgICAgICAgIGxhc3RfcmVzaWR1YWxfc3VyZmFjZSA8LSByZXNpZHVhbF9zdXJmYWNlDQogICAgICAgICAgICBsYXN0X3Jlc2lkdWFsX2luZGV4IDwtIGUNCiAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgIH0NCiAgICB9DQogIH0NCiAgDQojIHRoaXMgYml0IGVzdGltYXRlcyB0aGUgd2lkdGggb2YgdGhlIGNoYW5uZWwgd2hlbiBmbG93IGFwcHJvYWNoZXMgemVybyAodGhlIHJlc2lkdWFsIHdpZHRoKSBieSB1c2luZyB0aGUgcmF0aW8gb2YgcmVzaWR1YWwgZGVwdGhzIHRvIG9ic2VydmVkIGRlcHRocw0KICByZXNpZHVhbHMuZGYkcmVzaWR1YWxfd2lkdGggPC0gaWZlbHNlKA0KICAgIGlzLm5hKHJlc2lkdWFscy5kZiRyZXNpZHVhbF9kZXB0aCkgfCBpcy5uYShyZXNpZHVhbHMuZGYkVGhhbHdlZ19EZXB0aF9tKSB8IHJlc2lkdWFscy5kZiRUaGFsd2VnX0RlcHRoX20gPT0gMCwNCiAgICBOQSwNCiAgICB3ZXR3aWR0aCAqIChyZXNpZHVhbHMuZGYkcmVzaWR1YWxfZGVwdGggLyByZXNpZHVhbHMuZGYkVGhhbHdlZ19EZXB0aF9tKQ0KICApDQogIA0KICByZXR1cm4ocmVzaWR1YWxzLmRmKQ0KfQ0KDQojIE5vdyB3ZSB3aWxsIGFwcGx5IHRoaXMgZnVuY3Rpb24gYWNyb3NzIGFsbCBzaXRlcyBhbmQgeWVhcnMNCiMgR3JvdXAgYnkgU2l0ZSBhbmQgWWVhciwgYW5kIGFwcGx5IHRoZSBjYWxjdWxhdGVfcmVzaWR1YWxfZGVwdGhzIGZ1bmN0aW9uDQpyZXNpZHVhbHMuZGYgPC0gZGYgJT4lDQogIGdyb3VwX2J5KFNpdGUsIHllYXIpICU+JQ0KICBkbyhjYWxjdWxhdGVfcmVzaWR1YWxfZGVwdGhzKC4pKSAlPiUNCiAgdW5ncm91cCgpDQpgYGANCg0KQmVsb3cgd2UgZ2VuZXJhdGUgYSBxdWljayB2aXN1YWwgb2YgdGhlIGRlcHRocyBhbmQgcmVzaWR1YWwgc3VyZmFjZXMgdGhhdCB3ZXJlIHByb2plY3RlZCBieSB0aGUgY29kZS4gVGFrZSBhIGxvb2sgdG8gZW5zdXJlIGl0IG1hdGNoZXMgeW91ciB1bmRlcnN0YW5kaW5nIG9mIHJlc2lkdWFsIHBvb2xzIGFuZCBsb29rIGZvciBwb3RlbnRpYWwgZXJyb3JzICh0aGUgZmlndXJlIGlzIGludGVyYWN0aXZlLCBzbyB6b29tIGluIGlmIHlvdSBoYXZlIHNldmVyYWwgcGxvdHMpLiBUcnkgdG8gaWRlbnRpZnkgc29tZSBsb2NhbCBkZXB0aCBtaW5pbWEgdGhhdCBhcmUgd2l0aGluIGEgcG9vbCAoaWYgcHJlc2VudCBpbiB5b3VyIGRhdGEpLCBhbmQgY29tcGFyZSB0aGVzZSB0byB0aGUgbG9jYWwgZGVwdGggbWluaW1hIHRoYXQgYWN0IGFzIHBvb2wgb3V0bGV0cyAtIHRoZSBzaGFsbG93ZXIgZmVhdHVyZXMgYXQgd2hpY2ggcmVzaWR1YWwgc3VyZmFjZXMgYmVnaW4uIFJlbWVtYmVyIHRoYXQgdGhlIHJlc2lkdWFsIHN1cmZhY2Ugc2xvcGVzIGRvd24gaW4gdGhlc2UgZmlndXJlcyBhcyB5b3UgcHJvZ3Jlc3MgdXBzdHJlYW0gKHJpZ2h0IGluIHRoZSBwbG90cyksIHdoaWNoIGlzIHRvIGNvbXBlbnNhdGUgZm9yIHRoZSBmYWN0IHRoYXQgdGhlIHRydWUgdGhhbHdlZyBzdXJmYWNlIHNsb3BlcyBkb3duIGFzIHlvdSBwcm9ncmVzcyBkb3duc3RyZWFtLg0KDQpgYGB7ciB2aXN1YWxpc2UgcmVzaWR1YWwgc3VyZmFjZXMsIGVjaG8gPSBGQUxTRX0NCiMgRW5zdXJlICd5ZWFyJyBpcyBvcmRlcmVkIGZyb20gb2xkZXN0IHRvIHlvdW5nZXN0DQpyZXNpZHVhbHMuZGYkeWVhciA8LSBmYWN0b3IocmVzaWR1YWxzLmRmJHllYXIsIGxldmVscyA9IHNvcnQodW5pcXVlKHJlc2lkdWFscy5kZiR5ZWFyKSwgZGVjcmVhc2luZyA9IEZBTFNFKSkNCg0KZ2c8LSBnZ3Bsb3QocmVzaWR1YWxzLmRmLCBhZXMoeCA9IGRpc3RhbmNlKSkgKw0KICAjIFBsb3QgVGhhbHdlZyBEZXB0aCBhcyBhIGxpbmUNCiAgZ2VvbV9saW5lKGFlcyh5ID0gLVRoYWx3ZWdfRGVwdGhfbSksIGNvbG9yID0gImJsYWNrIiwgbGluZXdpZHRoID0gMSwgbGluZXR5cGUgPSAic29saWQiKSArDQogIA0KICAjIFBsb3QgUmVzaWR1YWwgU3VyZmFjZSBhcyBwb2ludHMgKGluc3RlYWQgb2YgbGluZSwgd2hpY2ggd291bGQgJ2p1bXAnIHVwIGF0IHVwc3RyZWFtIG9mIHNvbWUgcG9vbHMpDQogIGdlb21fcG9pbnQoYWVzKHkgPSAtcmVzaWR1YWxfc3VyZmFjZSksIGNvbG9yID0gImJsdWUiLCBzaXplID0gMSkgKw0KICANCiAgIyBBZGQgbGFiZWxzIGFuZCB0aXRsZQ0KICBsYWJzKHggPSAiRGlzdGFuY2UgKG0pIiwgeSA9ICJEZXB0aCAobSkiLCB0aXRsZSA9ICJUaGFsd2VnIERlcHRoIGFuZCBSZXNpZHVhbCBTdXJmYWNlIikgKw0KICANCiAgIyBGbGlwIHRoZSB5LWF4aXMgdG8gbWF0Y2ggdGhlIGludmVydGVkIGxpbmVzDQogICBzY2FsZV95X2NvbnRpbnVvdXMoDQogICAgbmFtZSA9ICJEZXB0aCAobSkiLCANCiAgICBicmVha3MgPSBzZXEoLW1heChyZXNpZHVhbHMuZGYkVGhhbHdlZ19EZXB0aF9tLCBuYS5ybSA9IFRSVUUpLCAwLCBieSA9IDAuMiksICANCiAgICBsYWJlbHMgPSBzY2FsZXM6Om51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjIsIGJpZy5tYXJrID0gIiIsIGRlY2ltYWwubWFyayA9ICIuIikoDQogICAgICBhYnMoc2VxKC1tYXgocmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbSwgbmEucm0gPSBUUlVFKSwgMCwgYnkgPSAwLjIpKQ0KICAgICkgICMgQ29udmVydCB0byBwb3NpdGl2ZSBmb3IgbGFiZWxzIGFuZCBlbnN1cmUgYWNjdXJhY3kgb2YgMiBkZWNpbWFscw0KICApICsNCiAgDQogICMgQ3VzdG9taXplIHRoZW1lDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiksDQogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiksDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksDQogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCwgZmFjZSA9ICJib2xkIikNCiAgKSArDQogIA0KICAjIFVzZSBmYWNldF9ncmlkIHRvIGFycmFuZ2UgYnkgU2l0ZSAocm93cykgYW5kIFllYXIgKGNvbHVtbnMpDQogIGZhY2V0X2dyaWQoU2l0ZSB+IHllYXIsIHNjYWxlcyA9ICJmaXhlZCIpICsgICMgUm93cyA9IFNpdGUsIENvbHVtbnMgPSBZZWFyIChvbGRlc3Qgb24gbGVmdCkNCiAgDQogICMgQ3VzdG9taXplIGdyaWQgc3BhY2luZyBpZiBuZWNlc3NhcnkNCiAgdGhlbWUoDQogICAgc3RyaXAudGV4dC55ID0gZWxlbWVudF90ZXh0KGFuZ2xlID05MCksICANCiAgICBwYW5lbC5zcGFjaW5nID0gdW5pdCgxLCAibGluZXMiKSAgIyBBZGp1c3Qgc3BhY2UgYmV0d2VlbiBwYW5lbHMNCiAgKQ0KaW50ZXJhY3RpdmVfcGxvdCA8LSBnZ3Bsb3RseShnZykNCmludGVyYWN0aXZlX3Bsb3QNCg0KIyBFeHBvcnQgYSBmaWd1cmUgKGNvbW1lbnRlZCBvdXQgaW4gZmF2b3VyIG9mIGJlbG93IGZpZ3VyZSkNCiMgZXhwb3J0X3Bsb3QoZ2csICJUaGFsd2VnIFdhdGVyIERlcHRoIGFuZCBSZXNpZHVhbCBTdXJmYWNlLnBkZiIpDQojIGV4cG9ydF9wbG90KGludGVyYWN0aXZlX3Bsb3QsICJUaGFsd2VnIFdhdGVyIERlcHRoIGFuZCBSZXNpZHVhbCBTdXJmYWNlLmh0bWwiKQ0KYGBgDQoNCiMgJ01lYW5pbmdmdWwnIFBvb2xzDQoNCkNvbnNpZGVyIHRoZSB2ZXJ0aWNhbCBleGFnZ2VyYXRpb24gb2YgdGhlIGFib3ZlIGZpZ3VyZSAtIHNvbWUgJ3Bvb2xzJyBtYXkgYmUgdmVyeSBzaGFsbG93IGluZGVlZCwgYW5kIG1pZ2h0IG5vdCBuZWNlc3NhcmlseSBjb3JyZXNwb25kIHdpdGggd2hhdCB5b3Ugd291bGQgYWN0dWFsbHkgY29uc2lkZXIgYSBwb29sIGluIGEgc3RyZWFtLiANCg0KSXQgaXMgcHJvYmFibHkgbW9zdCBpbmZvcm1hdGl2ZSB0byBjb25zaWRlciBtZXRyaWNzIHJlbGF0aW5nIG9ubHkgdG8gdGhvc2UgcG9vbHMgdGhhdCBhcmUgZXhwZWN0ZWQgdG8gYmUgaHlkcmF1bGljYWxseSBhbmQvb3IgYmlvbG9naWNhbGx5IG1lYW5pbmdmdWwuIFRoZSBjb2RlIG5vdyBkZXRlY3RzIHBvb2xzIGFuZCBhc3NpZ25zIGVhY2ggYSBwb29sIElELCBzbyB0aGF0IHdlIGNhbiBjaGFyYWN0ZXJpc2UgdGhlbSBpbmRpdmlkdWFsbHkgYW5kIHNlbGVjdCBzdWJzZXRzIGFzIGFwcHJvcHJpYXRlLg0KDQpgYGB7ciBJRCBhY3R1YWwgcG9vbHMsIGVjaG8gPSBGQUxTRX0NCmlkZW50aWZ5X3Jlc2lkdWFsX3Bvb2xzIDwtIGZ1bmN0aW9uKGRmKSB7DQogICMgSW5pdGlhbGl6ZSB0aGUgcG9vbCBJRCBjb2x1bW4NCiAgZGYkcG9vbF9pZCA8LSBhcy5jaGFyYWN0ZXIoTkEpICAjIERlZmF1bHQgaXMgTkEgKG5vdCBpbiBhIHBvb2wpDQogIA0KICAjIFZhcmlhYmxlcyB0byB0cmFjayBwb29sIHN0YXR1cw0KICBwb29sX2lkIDwtIDANCiAgaW5fcG9vbCA8LSBGQUxTRSAgIyBXaGV0aGVyIHdlIGFyZSBjdXJyZW50bHkgaW5zaWRlIGEgcG9vbA0KICANCiAgIyBJdGVyYXRlIHRocm91Z2ggcm93cyB0byBpZGVudGlmeSBwb29scw0KICBmb3IgKGkgaW4gMTpucm93KGRmKSkgew0KICAgICMgQ2hlY2sgaWYgdGhlIGN1cnJlbnQgcm93IHN0YXJ0cyBhIG5ldyBwb29sDQogICAgaWYgKCFpbl9wb29sICYmICFpcy5uYShkZiRMRE1faWRbaV0pKSB7DQogICAgICBwb29sX2lkIDwtIHBvb2xfaWQgKyAxICAjIEluY3JlbWVudCBwb29sIElEDQogICAgICBpbl9wb29sIDwtIFRSVUUgICMgRW50ZXIgYSBwb29sDQogICAgICBkZiRwb29sX2lkW2ldIDwtIHBvb2xfaWQgICMgQXNzaWduIHRoZSBuZXcgcG9vbCBJRCB0byB0aGlzIHJvdw0KICAgICAgbmV4dCAgIyBTa2lwIHRvIHRoZSBuZXh0IGl0ZXJhdGlvbiB0byBhdm9pZCBmdXJ0aGVyIGxvZ2ljIGZvciB0aGlzIHJvdw0KICAgIH0NCiAgICANCiAgICAjIElmIGFscmVhZHkgaW4gYSBwb29sLCBhc3NpZ24gdGhlIHBvb2wgSUQNCiAgICBpZiAoaW5fcG9vbCkgew0KICAgICAgZGYkcG9vbF9pZFtpXSA8LSBwb29sX2lkICAjIENvbnRpbnVlIGFzc2lnbmluZyB0aGUgY3VycmVudCBwb29sIElEDQogICAgICANCiAgICAgICMgQ2hlY2sgaWYgdGhlIGN1cnJlbnQgcm93IGVuZHMgdGhlIHBvb2wNCiAgICAgIGlmICghaXMubmEoZGYkcmVzaWR1YWxfZGVwdGhbaV0pICYmIGRmJHJlc2lkdWFsX2RlcHRoW2ldIDw9IDApIHsNCiAgICAgICAgaWYgKCFpcy5uYShkZiRMRE1faWRbaV0pKSB7DQogICAgICAgICAgIyBJZiB0aGUgY3VycmVudCByb3cgaXMgYSBMRE0sIHN0YXJ0IGEgbmV3IHBvb2wNCiAgICAgICAgICBwb29sX2lkIDwtIHBvb2xfaWQgKyAxDQogICAgICAgICAgZGYkcG9vbF9pZFtpXSA8LSBwb29sX2lkICAjIEFzc2lnbiB0aGUgbmV3IHBvb2wgSUQNCiAgICAgICAgICAjIENvbnRpbnVlIGluX3Bvb2wgPSBUUlVFIHNpbmNlIGEgbmV3IHBvb2wgc3RhcnRzDQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgIyBJZiB0aGUgY3VycmVudCByb3cgaXMgTk9UIGFuIExETSwgZW5kIHRoZSBwb29sDQogICAgICAgICAgaW5fcG9vbCA8LSBGQUxTRSAgIyBFeGl0IHRoZSBwb29sDQogICAgICAgIH0NCiAgICAgIH0NCiAgICB9DQogIH0NCiAgDQogIHJldHVybihkZikNCn0NCg0KIyBBcHBseSB0aGUgZnVuY3Rpb24gYWNyb3NzIGFsbCBTaXRlLVllYXIgY29tYmluYXRpb25zDQpyZXNpZHVhbHMuZGYgPC0gcmVzaWR1YWxzLmRmICU+JQ0KICBncm91cF9ieShTaXRlLCB5ZWFyKSAlPiUNCiAgZG8oaWRlbnRpZnlfcmVzaWR1YWxfcG9vbHMoLikpICU+JQ0KICB1bmdyb3VwKCkNCg0KIyBFbnN1cmUgcG9vbF9pZCBpcyBhIGZhY3RvciB3aXRoIG51bWVyaWMgb3JkZXJpbmcNCnJlc2lkdWFscy5kZiRwb29sX2lkIDwtIGZhY3RvcihyZXNpZHVhbHMuZGYkcG9vbF9pZCwgbGV2ZWxzID0gYXMuY2hhcmFjdGVyKHNvcnQoYXMubnVtZXJpYyh1bmlxdWUocmVzaWR1YWxzLmRmJHBvb2xfaWQpKSkpKQ0KDQojIEN1c3RvbSBwYWxldHRlIHdpdGggbW9yZSBkaXN0aW5jdCBjb2xvcnMgKHByaW9yaXR5IGlzIHRvIElEIHBvb2xzIGZyb20gYWRqYWNlbnQgb25lcykNCmN1c3RvbV9wYWxldHRlIDwtIGMoDQogICIjRTQxQTFDIiwgIiMzNzdFQjgiLCAiIzREQUY0QSIsICIjOTg0RUEzIiwgIiNGRjdGMDAiLCAiI0ZGRkYzMyIsICIjQTY1NjI4IiwgIiNGNzgxQkYiLCAiIzk5OTk5OSIsICIjNjZDMkE1IiwgIiNGQzhENjIiLCAiIzhEQTBDQiIsICIjRTc4QUMzIiwgIiNBNkQ4NTQiLCAiI0ZGRDkyRiIsICAgIiNFNUM0OTQiLCAiI0IzQjNCMyIsICIjMUI5RTc3IiwgIiNEOTVGMDIiKQ0KDQpnZzwtZ2dwbG90KHJlc2lkdWFscy5kZiwgYWVzKHggPSBkaXN0YW5jZSkpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gLVRoYWx3ZWdfRGVwdGhfbSksIGNvbG9yID0gImJsYWNrIiwgbGluZXdpZHRoID0gMSwgbGluZXR5cGUgPSAic29saWQiKSArDQogIGdlb21fcG9pbnQoYWVzKHkgPSAtcmVzaWR1YWxfc3VyZmFjZSksIGNvbG9yID0gImJsdWUiLCBzaXplID0gMSkgKw0KICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IC1UaGFsd2VnX0RlcHRoX20sIHltYXggPSAtcmVzaWR1YWxfc3VyZmFjZSwgZmlsbCA9IHBvb2xfaWQpLCBhbHBoYSA9IDAuNikgKw0KICBsYWJzKHggPSAiRGlzdGFuY2UgKG0pIiwgeSA9ICJEZXB0aCAobSkiLCB0aXRsZSA9ICJSZXNpZHVhbCBQb29scyIsIGZpbGwgPSAiUG9vbCBJRCIpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgIG5hbWUgPSAiRGVwdGggKG0pIiwgDQogICAgYnJlYWtzID0gc2VxKC1tYXgocmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbSwgbmEucm0gPSBUUlVFKSwgMCwgYnkgPSAwLjIpLA0KICAgIGxhYmVscyA9IHNjYWxlczo6bnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMiwgYmlnLm1hcmsgPSAiIiwgZGVjaW1hbC5tYXJrID0gIi4iKSgNCiAgICAgIGFicyhzZXEoLW1heChyZXNpZHVhbHMuZGYkVGhhbHdlZ19EZXB0aF9tLCBuYS5ybSA9IFRSVUUpLCAwLCBieSA9IDAuMikpDQogICAgKQ0KICApICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY3VzdG9tX3BhbGV0dGUpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKSwNCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKSwNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwNCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4LCBmYWNlID0gImJvbGQiKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiDQogICkgKw0KICBmYWNldF9ncmlkKFNpdGUgfiB5ZWFyLCBzY2FsZXMgPSAiZml4ZWQiKQ0KDQppbnRlcmFjdGl2ZV9wbG90IDwtIGdncGxvdGx5KGdnKQ0KaW50ZXJhY3RpdmVfcGxvdA0KDQojIEV4cG9ydCBhIGZpZ3VyZQ0KZXhwb3J0X3Bsb3QoZ2csICJEZXB0aCBhbmQgUmVzaWR1YWwgU3VyZmFjZSAtIFBvb2xzIElEZC5wZGYiKQ0KZXhwb3J0X3Bsb3QoaW50ZXJhY3RpdmVfcGxvdCwgIkRlcHRoIGFuZCBSZXNpZHVhbCBTdXJmYWNlIC0gUG9vbHMgSURkLmh0bWwiKQ0KYGBgDQoNClRoZSBhYm92ZSBmaWd1cmUgc2hvdWxkIHNob3cgYSBzZXJpZXMgb2YgZGlzdGluY3QgcG9vbHMgYW5kIGlzIGV4cG9ydGVkIHRvIHlvdXIgb3V0cHV0IGZvbGRlci4gRG9uJ3Qgd29ycnkgaWYgdGhlIHNoYWRpbmcgY3V0cyBvZmYgYmVmb3JlIHRoZSBwb29sJ3MgdXBzdHJlYW0gZXh0ZW50LCB0aGlzIGlzIGp1c3QgYW4gYXJ0ZWZhY3QgYXNzb2NpYXRlZCB3aXRoIG15IGxpbWl0ZWQgZmlndXJlLXBsb3R0aW5nIGFiaWxpdGllcy4gVGhlIGltcG9ydGFudCB0aGluZyB0byBub3RlIGlzIHRoYXQgdGhlIGNhbGN1bGF0aW9ucyBiZWxvdyB3aWxsIGludGVncmF0ZSB0aGUgZnVsbCBhcmVhIGJlbmVhdGggdGhlIHJlc2lkdWFsIHN1cmZhY2UgZm9yIGVhY2ggcG9vbC4NCg0KIyMgUG9vbCBNZXRyaWNzDQoNClRoZSBjb2RlIG5vdyBjYWxjdWxhdGVzIHRoZSBmb2xsb3dpbmcgbWV0cmljcyBmb3IgZWFjaCByZXNpZHVhbCBwb29sOg0KDQotIE1heGltdW0gZGVwdGg7DQoNCi0gUG9vbCBsZW5ndGggKHBvb2wgb3V0bGV0IHRvIHdoZXJlIHRoZSByZXNpZHVhbCBzdXJmYWNlIG1lZXRzIHRoZSB0aGFsd2VnIGF0IHRoZSB1cHN0cmVhbSBlbmQgb2YgdGhlIHBvb2wpOyBhbmQNCg0KLSBTYWdpdHRhbCBhcmVhLg0KDQpTYWdpdHRhbCByZWZlcnMgdG8gYSBwbGFuZSB0aGF0IGRpdmlkZXMgYSBib2R5IGludG8gbGVmdCBhbmQgcmlnaHQsIHNvIGltYWdpbmUgYSB0d28tZGltZW5zaW9uYWwgdmVydGljYWwgc2NyZWVuIGV4dGVuZGluZyBkb3duc3RyZWFtIGFsbCBhbG9uZyB0aGUgdGhhbHdlZywgc2VwYXJhdGluZyByaXZlciBsZWZ0IGZyb20gcml2ZXIgcmlnaHQuIFdpdGhpbiBlYWNoIHJlc2lkdWFsIHBvb2wsIHRoZSBzYWdpdHRhbCBhcmVhIGNvcnJlc3BvbmRzIHRvIHRoZSBzdXJmYWNlIGFyZWEgb2YgdGhhdCBzY3JlZW4uIFRvbyBhYnN0cmFjdD8gVGFrZSBhIGxvb2sgYXQgdGhlIGFib3ZlIGZpZ3VyZSBhZ2FpbjogRWFjaCBvZiB0aGUgc2hhZGVkIGFyZWFzIGNvcnJlc3BvbmRzIHRvIHRoZSBzYWdpdHRhbCBhcmVhIGZvciB0aGF0IHBhcnRpY3VsYXIgcmVzaWR1YWwgcG9vbCAtIHNhZ2l0dGFsIGFyZWEgaW50ZWdyYXRlcyBlYWNoIGRlcHRoIG1lYXN1cmVtZW50IG92ZXIgdGhlIGxlbmd0aCBvZiB0aGUgcG9vbC4gQWx0aG91Z2ggdGhpcyBtYXkgbm90IGJlIGFzIGludHVpdGl2ZSBhcyBwb29sIHZvbHVtZSwgaXQgcmVxdWlyZXMgZmV3ZXIgYXNzdW1wdGlvbnMgdGhhbiB3aWxsIGJlIG5lY2Vzc2FyeSB0byBnZW5lcmF0ZSBlc3RpbWF0ZXMgb2YgcG9vbCB2b2x1bWUgKGkuZS4sIHJlZ2FyZGluZyBjcm9zcy1zZWN0aW9uYWwgY2hhbm5lbCBzaGFwZSBvZiBwb29scyBhdCB6ZXJvIGZsb3csIHdldHRlZCB3aWR0aHMpLiBCZWNhdXNlIGZld2VyIGFzc3VtcHRpb25zIGFyZSByZXF1aXJlZCwgYW5kIGJlY2F1c2UgaXQgZWFzaWx5IGNvcnJlc3BvbmRzIHRvIDJEIHZpc3VhbGlzYXRpb25zIGxpa2UgdGhlIG9uZSBhYm92ZSwgd2UgcmVjb21tZW5kIHVzaW5nIHNhZ2l0dGFsIGFyZWEgcmF0aGVyIHRoYW4gdm9sdW1lIGZvciBhIG1ldHJpYyB0cmFja2luZyBjaGFuZ2VzIGluIHBvb2wgaGFiaXRhdCAodGhvdWdoIHdlIHdpbGwgYWxzbyBjYWxjdWxhdGUgdm9sdW1lIGxhdGVyKS4NCg0KYGBge3Igc2FnaXR0YWwgYXJlYSwgbWF4IGRlcHRocywgcG9vbCBsZW5ndGhzLCBlY2hvID0gRkFMU0V9DQpjcmVhdGVfcG9vbF9zdW1tYXJ5X3RhYmxlIDwtIGZ1bmN0aW9uKHJlc2lkdWFscy5kZiwgY3VzdG9tX2RlcHRoX3RocmVzaG9sZCA9IE5VTEwpIHsNCiAgIyBSZW1vdmUgcm93cyB3aXRoIG5lZ2F0aXZlIGRpc3RhbmNlIHZhbHVlcw0KICByZXNpZHVhbHMuZGYgPC0gcmVzaWR1YWxzLmRmW3Jlc2lkdWFscy5kZiRkaXN0YW5jZSA+PSAwLCBdDQogIA0KICAjIEVuc3VyZSB0aGUgZGF0YWZyYW1lIGlzIHNvcnRlZCBieSBkaXN0YW5jZQ0KICByZXNpZHVhbHMuZGYgPC0gcmVzaWR1YWxzLmRmW29yZGVyKHJlc2lkdWFscy5kZiRkaXN0YW5jZSksIF0NCiAgDQogICMgRmlsdGVyIG91dCByb3dzIHdoZXJlIHBvb2xfaWQgaXMgTkENCiAgcmVzaWR1YWxzLmRmIDwtIHJlc2lkdWFscy5kZlshaXMubmEocmVzaWR1YWxzLmRmJHBvb2xfaWQpLCBdDQogIA0KICAjIEluaXRpYWxpemUgYSBsaXN0IHRvIHN0b3JlIHJlc3VsdHMgZm9yIGVhY2ggc2l0ZS15ZWFyIGNvbWJpbmF0aW9uDQogIHBvb2xfc3VtbWFyeV9saXN0IDwtIGxpc3QoKQ0KDQogICMgR3JvdXAgdGhlIGRhdGFmcmFtZSBieSBTaXRlIGFuZCBZZWFyDQogIHJlc2lkdWFscy5kZl9ncm91cGVkIDwtIHNwbGl0KHJlc2lkdWFscy5kZiwgbGlzdChyZXNpZHVhbHMuZGYkU2l0ZSwgcmVzaWR1YWxzLmRmJHllYXIpKQ0KICANCiAgIyBJdGVyYXRlIG92ZXIgZWFjaCBTaXRlLVllYXIgZ3JvdXANCiAgZm9yIChncm91cF9uYW1lIGluIG5hbWVzKHJlc2lkdWFscy5kZl9ncm91cGVkKSkgew0KICAgIGdyb3VwIDwtIHJlc2lkdWFscy5kZl9ncm91cGVkW1tncm91cF9uYW1lXV0NCiAgICANCiAgICAjIENhbGN1bGF0ZSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHJlc2lkdWFsIGRlcHRocyBmb3IgdGhpcyBncm91cA0KICAgIHNkX3Jlc2lkdWFsX2RlcHRoIDwtIHNkKGdyb3VwJHJlc2lkdWFsX2RlcHRoLCBuYS5ybSA9IFRSVUUpDQogICAgDQogICAgIyBJbml0aWFsaXplIGEgbGlzdCB0byBzdG9yZSByZXN1bHRzIGZvciBlYWNoIHBvb2wgaW4gdGhlIGN1cnJlbnQgZ3JvdXANCiAgICBwb29sX3N1bW1hcnkgPC0gbGlzdCgpDQogICAgDQogICAgIyBJdGVyYXRlIG92ZXIgdW5pcXVlIHBvb2xfaWRzIHRvIGNhbGN1bGF0ZSBtYXggcmVzaWR1YWwgZGVwdGggYW5kIHNhZ2l0dGFsIGFyZWEgZm9yIGVhY2ggcG9vbA0KICAgIHVuaXF1ZV9wb29sX2lkcyA8LSB1bmlxdWUoZ3JvdXAkcG9vbF9pZCkNCiAgICBmb3IgKHBvb2xfaWQgaW4gdW5pcXVlX3Bvb2xfaWRzKSB7DQogICAgICAjIFN1YnNldCB0aGUgZGF0YWZyYW1lIGZvciB0aGUgY3VycmVudCBwb29sDQogICAgICBwb29sX2RhdGEgPC0gZ3JvdXBbZ3JvdXAkcG9vbF9pZCA9PSBwb29sX2lkLCBdDQogICAgICANCiAgICAgICMgQ2FsY3VsYXRlIHRoZSBtYXhpbXVtIHJlc2lkdWFsIGRlcHRoIGZvciB0aGUgcG9vbA0KICAgICAgbWF4X3Jlc2lkdWFsX2RlcHRoIDwtIG1heChwb29sX2RhdGEkcmVzaWR1YWxfZGVwdGgsIG5hLnJtID0gVFJVRSkNCiAgICAgIA0KICAgICAgIyBBcHBseSBzZWxlY3Rpb24gY3JpdGVyaWE6IGVpdGhlciB0aGUgbWF4IHJlc2lkdWFsIGRlcHRoIGlzID49IHNkIG9yIHRoZSBjdXN0b20gdGhyZXNob2xkIGlzIG1ldA0KICAgICAgaWYgKCFpcy5udWxsKGN1c3RvbV9kZXB0aF90aHJlc2hvbGQpKSB7DQogICAgICAgICMgVXNlIHRoZSBjdXN0b20gZGVwdGggdGhyZXNob2xkIGZvciBzZWxlY3Rpb24NCiAgICAgICAgaWYgKG1heF9yZXNpZHVhbF9kZXB0aCA8IGN1c3RvbV9kZXB0aF90aHJlc2hvbGQpIHsNCiAgICAgICAgICBuZXh0ICAjIFNraXAgdGhpcyBwb29sIGlmIGl0IGRvZXNuJ3QgbWVldCB0aGUgY3VzdG9tIHRocmVzaG9sZA0KICAgICAgICB9DQogICAgICB9IGVsc2Ugew0KICAgICAgICAjIFVzZSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSBncm91cCBmb3Igc2VsZWN0aW9uIGlmIG5vIGN1c3RvbSB0aHJlc2hvbGQgaXMgcHJvdmlkZWQNCiAgICAgICAgaWYgKG1heF9yZXNpZHVhbF9kZXB0aCA8IHNkX3Jlc2lkdWFsX2RlcHRoKSB7DQogICAgICAgICAgbmV4dCAgIyBTa2lwIHRoaXMgcG9vbCBpZiBpdCBkb2Vzbid0IG1lZXQgdGhlIFNEIHRocmVzaG9sZA0KICAgICAgICB9DQogICAgICB9DQogICAgICANCiAgICAgICMgSW5pdGlhbGl6ZSB2YXJpYWJsZSB0byBhY2N1bXVsYXRlIGFyZWEgZm9yIHRoaXMgcG9vbA0KICAgICAgc2FnaXR0YWxfYXJlYSA8LSAwDQogICAgICANCiAgICAgICMgSXRlcmF0ZSB0aHJvdWdoIHRoZSBkYXRhZnJhbWUgZm9yIHRoaXMgcG9vbCBhbmQgY2FsY3VsYXRlIHRoZSBhcmVhDQogICAgICBmb3IgKGkgaW4gMToobnJvdyhwb29sX2RhdGEpIC0gMSkpIHsgICMgbG9vcCB0byBhdm9pZCBvdXQtb2YtYm91bmRzIGluZGV4DQogICAgICAgIHJlc2lkdWFsX2RlcHRoIDwtIHBvb2xfZGF0YSRyZXNpZHVhbF9kZXB0aFtpXQ0KICAgICAgICANCiAgICAgICAgIyBTa2lwIHRoZSBpdGVyYXRpb24gaWYgcmVzaWR1YWwgZGVwdGggaXMgTkEgDQogICAgICAgIGlmIChpcy5uYShyZXNpZHVhbF9kZXB0aCkpIHsNCiAgICAgICAgICBuZXh0ICAjIFNraXAgdG8gdGhlIG5leHQgaXRlcmF0aW9uIGlmIHJlc2lkdWFsIGRlcHRoIGlzIE5BDQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgICMgQ2FsY3VsYXRlIHRoZSBzcGFjaW5nIChkaXN0YW5jZSkgYmV0d2VlbiB0aGUgY3VycmVudCBhbmQgZm9sbG93aW5nIHBvaW50cw0KICAgICAgICBzcGFjaW5nIDwtIGFicyhwb29sX2RhdGEkZGlzdGFuY2VbaSArIDFdIC0gcG9vbF9kYXRhJGRpc3RhbmNlW2ldKQ0KICAgICAgICANCiAgICAgICAgIyBBZGQgdG8gdGhlIGFyZWEgaWYgcmVzaWR1YWwgZGVwdGggaXMgZ3JlYXRlciB0aGFuIDANCiAgICAgICAgc2FnaXR0YWxfYXJlYSA8LSBzYWdpdHRhbF9hcmVhICsgKHJlc2lkdWFsX2RlcHRoICogc3BhY2luZykNCiAgICAgIH0NCiAgICAgIA0KICAgICAgIyBIYW5kbGUgdGhlIGxhc3Qgcm93IGNvbnRyaWJ1dGlvbiB0byBzYWdpdHRhbCBhcmVhDQogICAgICBsYXN0X3JvdyA8LSBwb29sX2RhdGFbbnJvdyhwb29sX2RhdGEpLCBdDQogICAgICBpZiAoIWlzLm5hKGxhc3Rfcm93JHJlc2lkdWFsX2RlcHRoKSAmJiBsYXN0X3JvdyRyZXNpZHVhbF9kZXB0aCA+IDApIHsNCiAgICAgICAgbmV4dF9wb29sX3N0YXJ0IDwtIGdyb3VwW2dyb3VwJGRpc3RhbmNlID4gbGFzdF9yb3ckZGlzdGFuY2UgJiAhaXMubmEoZ3JvdXAkcG9vbF9pZCksIF0NCiAgICAgICAgaWYgKG5yb3cobmV4dF9wb29sX3N0YXJ0KSA+IDApIHsNCiAgICAgICAgICBuZXh0X2Rpc3RhbmNlIDwtIG5leHRfcG9vbF9zdGFydCRkaXN0YW5jZVsxXQ0KICAgICAgICAgIHNwYWNpbmcgPC0gYWJzKG5leHRfZGlzdGFuY2UgLSBsYXN0X3JvdyRkaXN0YW5jZSkNCiAgICAgICAgICBzYWdpdHRhbF9hcmVhIDwtIHNhZ2l0dGFsX2FyZWEgKyAobGFzdF9yb3ckcmVzaWR1YWxfZGVwdGggKiBzcGFjaW5nKQ0KICAgICAgICB9DQogICAgICB9DQogICAgICANCiAgICAgICMgQ2FsY3VsYXRlIHRoZSBwb29sIGxlbmd0aA0KICAgICAgbWluX2Rpc3RhbmNlIDwtIG1pbihwb29sX2RhdGEkZGlzdGFuY2UsIG5hLnJtID0gVFJVRSkNCiAgICAgIG1heF9kaXN0YW5jZSA8LSBtYXgocG9vbF9kYXRhJGRpc3RhbmNlLCBuYS5ybSA9IFRSVUUpDQogICAgICBwb29sX2xlbmd0aCA8LSBpZmVsc2UobWluX2Rpc3RhbmNlIDwgMCwgbWF4X2Rpc3RhbmNlLCBtYXhfZGlzdGFuY2UgLSBtaW5fZGlzdGFuY2UpDQogICAgICANCiAgICAgICMgU3RvcmUgdGhlIHJlc3VsdHMgZm9yIHRoZSBjdXJyZW50IHBvb2wNCiAgICAgIHBvb2xfc3VtbWFyeVtbYXMuY2hhcmFjdGVyKHBvb2xfaWQpXV0gPC0gbGlzdChtYXhfcmVzaWR1YWxfZGVwdGggPSBtYXhfcmVzaWR1YWxfZGVwdGgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FnaXR0YWxfYXJlYSA9IHNhZ2l0dGFsX2FyZWEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9vbF9sZW5ndGggPSBwb29sX2xlbmd0aCkNCiAgICB9DQogICAgDQogICAgIyBDb252ZXJ0IHRoZSByZXN1bHRzIGludG8gYSBkYXRhIGZyYW1lIGZvciB0aGUgY3VycmVudCBzaXRlLXllYXIgY29tYmluYXRpb24NCiAgICBwb29sX3N1bW1hcnlfZGYgPC0gZGF0YS5mcmFtZShwb29sX2lkID0gbmFtZXMocG9vbF9zdW1tYXJ5KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhfcmVzaWR1YWxfZGVwdGggPSBzYXBwbHkocG9vbF9zdW1tYXJ5LCBmdW5jdGlvbih4KSB4JG1heF9yZXNpZHVhbF9kZXB0aCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FnaXR0YWxfYXJlYSA9IHNhcHBseShwb29sX3N1bW1hcnksIGZ1bmN0aW9uKHgpIHgkc2FnaXR0YWxfYXJlYSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9vbF9sZW5ndGggPSBzYXBwbHkocG9vbF9zdW1tYXJ5LCBmdW5jdGlvbih4KSB4JHBvb2xfbGVuZ3RoKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTaXRlID0gdW5pcXVlKGdyb3VwJFNpdGUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHllYXIgPSB1bmlxdWUoZ3JvdXAkeWVhcikpDQogICAgDQogICAgIyBBcHBlbmQgdGhpcyBzdW1tYXJ5IHRvIHRoZSBtYWluIHBvb2xfc3VtbWFyeV9saXN0DQogICAgcG9vbF9zdW1tYXJ5X2xpc3RbW2dyb3VwX25hbWVdXSA8LSBwb29sX3N1bW1hcnlfZGYNCiAgfQ0KICANCiAgIyBDb21iaW5lIGFsbCBzaXRlLXllYXIgcG9vbCBzdW1tYXJpZXMgaW50byBhIHNpbmdsZSBkYXRhZnJhbWUNCiAgZmluYWxfcG9vbF9zdW1tYXJ5X2RmIDwtIGRvLmNhbGwocmJpbmQsIHBvb2xfc3VtbWFyeV9saXN0KQ0KICANCiAgIyBBZGQgY3VzdG9tX2RlcHRoX3RocmVzaG9sZCBhcyBhbiBhdHRyaWJ1dGUgdG8gdGhlIGRhdGEgZnJhbWUNCiAgYXR0cihmaW5hbF9wb29sX3N1bW1hcnlfZGYsICJjdXN0b21fZGVwdGhfdGhyZXNob2xkIikgPC0gY3VzdG9tX2RlcHRoX3RocmVzaG9sZA0KICANCiAgIyBSZXR1cm4gdGhlIGZpbmFsIHN1bW1hcnkgdGFibGUNCiAgcmV0dXJuKGZpbmFsX3Bvb2xfc3VtbWFyeV9kZikNCn0NCg0KIyB0aGlzIGlzIGEgZnVuY3Rpb24uIEl0IGRvZXMgbm90IGFjdHVhbGx5IHByb2R1Y2UgYSBuZXcgZGF0YWZyYW1lIHlldC4gVGhlIG5leHQgY2h1bmsgd2lsbC4uLg0KYGBgDQoNCiMjIFN1YnNldHRpbmcgUG9vbHMNCg0KU28gZmFyIHdlIGhhdmUgaWRlbnRpZmllZCBhbGwgb2YgdGhlIHJlc2lkdWFsIHBvb2xzLCBidXQgZGVwZW5kaW5nIG9uIHlvdXIgZGF0YXNldCBzb21lIG9mIHRoZSBwb29scyB2aXN1YWxpc2VkIGFib3ZlIG1pZ2h0IGxvb2sgbW9yZSBsaWtlIHB1ZGRsZXMuIFNvIHRvIGZvY3VzIG91ciBzdW1tYXJ5IHN0YXRpc3RpY3Mgb24gcG9vbHMgdGhhdCBiZXR0ZXIgYWxpZ24gd2l0aCB3aGF0IHdlIGNvbnNpZGVyIGJpb2xvZ2ljYWxseS0gYW5kL29yIGdlb21vcnBoaWNhbGx5LW1lYW5pbmdmdWwsIHdlIGNhbiB1c2UgdGhlIG1ldHJpY3Mgd2UganVzdCBjYWxjdWxhdGVkIHRvIGZvY3VzIG9uIGEgc3BlY2lmaWMgc3Vic2V0IG9mIGRlZXBlciBwb29scy4NCg0KSW4gdGVybXMgb2Ygc3Vic2V0dGluZyBwb29scywgc29tZSBwZW9wbGUgdXNlIGEgc3BlY2lmaWMgZGVwdGggY3V0LW9mZiBmb3IgYSBzcGVjaWVzIG9mIGludGVyZXN0IChlLmcuLCBNb3Nzb3AgYW5kIEJyYWRmb3JkIDIwMDYgdXNlZCAwLjEgbSkuIEFsdGVybmF0aXZlbHkgdGhlIHBvb2xzIHRoYXQgd2UgZm9jdXMgb24gY2FuIGJlIGJhc2VkIG9uIHBoeXNpY2FsIGNoYXJhY3RlcmlzdGljcyBvZiB0aGUgc2FtcGxlZCByZWFjaC4gV2Ugd2lsbCBkbyB0aGUgbGF0dGVyLCBrZWVwaW5nIHRoaXMgY29kZSBtb3JlIHdpZGVseSBhcHBsaWNhYmxlLCBieSBmb2xsb3dpbmcgU3RhY2sgKDE5ODkpIHdobyBkZXRlcm1pbmVkIG1lYW5pbmdmdWwgcG9vbHMgYXMgdGhvc2UgdGhhdCBoYWQgYSBtYXhpbXVtIGRlcHRoIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIGRlcHRoIGZvciB0aGUgcmVhY2guIA0KDQpJbiB0aGUgZm9sbG93aW5nIGNvZGUgY2h1bmsgaXQgcmVhZHMgJ2N1c3RvbV9kZXB0aCA8LSBOVUxMJy4gVGhpcyBpcyBvdXIgZGVmYXVsdCBzdWJzZXR0aW5nIChzZWxlY3RzIG9ubHkgcG9vbHMgd2l0aCBhIG1heGltdW0gcmVzaWR1YWwgZGVwdGggZ3JlYXRlciB0aGFuIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIHJlc2lkdWFsIGRlcHRocyBmb3IgdGhlIGVudGlyZSBzYW1wbGVkIHJlYWNoKS4gSWYgeW91IHdhbnQgdG8gc3Vic2V0IHRoZSBwb29scyBpbiBhbm90aGVyIHdheSwgeW91IGNhbiBtb2RpZnkgdGhlIGNvZGUgaGVyZS4gRm9yIGV4YW1wbGUsIGlmIGl0IGlzIGJpb2xvZ2ljYWxseSBtZWFuaW5nZnVsIGZvciB5b3VyIHN5c3RlbSB0byBjb25zaWRlciBvbmx5IHBvb2xzIHRoYXQgYXJlIDAuMSBtIGRlZXAgb3IgZ3JlYXRlciBkdXJpbmcgYXBwcm9hY2hpbmctemVyby1mbG93IHBlcmlvZHMsIHlvdSBjYW4gc3BlY2lmeSAnY3VzdG9tX2RlcHRoIDwtIDAuMScuIE9yLCBpZiB5b3Ugd2FudCB0byBjb25zaWRlciBhbGwgcG9vbHMgbm8gbWF0dGVyIGhvdyBzaGFsbG93LCB0aGVuIGFzc2lnbiBjdXN0b21fZGVwdGggYSB2YWx1ZSBvZiAnMCcuIEp1c3QgYmUgc3VyZSB0byBjb21wYXJlIGxpa2UtZm9yLWxpa2Ugd2hlbiB5b3UgY29uc2lkZXIgZGlmZmVyZW50IHllYXJzL3NpdGVzIHRoYXQgeW91IG1heSB3aXNoIHRvIGNvbXBhcmUuDQoNCmBgYHtyIGN1c3RvbSBkZXB0aCB0aHJlc2hvbGR9DQojIEFkZCBhIGN1c3RvbSBkZXB0aCB0aHJlc2hvbGQgaW4gbWV0cmVzLCBvciBsZWF2ZSBhcyAnTlVMTCcgdG8gdXNlIHN0YW5kYXJkIGRldmlhdGlvbi4gSWYgeW91IGFyZSBpbnRlcmVzdGVkIGluIGFsbCBvZiB0aGUgcmVzaWR1YWwgZGVwdGhzIChpLmUuLCBub3Qgc3Vic2V0dGluZyksIGp1c3QgZW50ZXIgJzAnIGZvciB0aGUgY3VzdG9tX2RlcHRoDQpjdXN0b21fZGVwdGggPC0gTlVMTA0KYGBgDQoNCmBgYHtyIHRhYmxlIG9mIG1heCBkZXB0aCwgc2FnaXR0YWwgYXJlYSwgcG9vbCBsZW5ndGgsIGVjaG8gPSBGQUxTRX0NCnBvb2xfc3VtbWFyeV9yZXN1bHQgPC0gY3JlYXRlX3Bvb2xfc3VtbWFyeV90YWJsZShyZXNpZHVhbHMuZGYsIGN1c3RvbV9kZXB0aF90aHJlc2hvbGQgPSBjdXN0b21fZGVwdGgpDQpwb29sX3N1bW1hcnlfcmVzdWx0JHBvb2xfaWQgPC0gYXMuY2hhcmFjdGVyKHBvb2xfc3VtbWFyeV9yZXN1bHQkcG9vbF9pZCkNCnBvb2xfc3VtbWFyeV9yZXN1bHQgPC0gcG9vbF9zdW1tYXJ5X3Jlc3VsdCAlPiUNCiAgc2VsZWN0KFNpdGUsIHllYXIsIGV2ZXJ5dGhpbmcoKSkgICMgTW92ZSBTaXRlIGFuZCBZZWFyIHRvIHRoZSBsZWZ0DQpkYXRhdGFibGUoDQogIHBvb2xfc3VtbWFyeV9yZXN1bHQsDQogIGNhcHRpb24gPSAiUmVzaWR1YWwgUG9vbCBTdW1tYXJ5IGJ5IFBvb2w6IE1heGltdW0gRGVwdGgsIExlbmd0aCwgU2FnaXR0YWwgQXJlYSIsDQogIHJvd25hbWVzID0gRkFMU0UsICAjIEhpZGUgcm93IG51bWJlcnMNCiAgb3B0aW9ucyA9IGxpc3QoDQogICAgcGFnZUxlbmd0aCA9IDEwLCAgIyBOdW1iZXIgb2Ygcm93cyBwZXIgcGFnZQ0KICAgIGF1dG9XaWR0aCA9IFRSVUUNCiAgKQ0KKSU+JQ0KICBmb3JtYXRSb3VuZChjb2x1bW5zID0gbmFtZXMocG9vbF9zdW1tYXJ5X3Jlc3VsdClbc2FwcGx5KHBvb2xfc3VtbWFyeV9yZXN1bHQsIGlzLm51bWVyaWMpXSwgZGlnaXRzID0gMykNCg0KIyBFeHBvcnQgdGFibGUNCmV4cG9ydF90YWJsZShhcy5kYXRhLmZyYW1lKHBvb2xfc3VtbWFyeV9yZXN1bHQpLCAiUmVzaWR1YWwgUG9vbCBJbmRpdmlkdWFsIE1heCBEZXB0aCBMZW5ndGggU2FnaXR0YWwuY3N2IikNCmBgYA0KDQpUaGUgdGFibGUgYWJvdmUgaGFzIGJlZW4gZXhwb3J0ZWQgdG8geW91ciBvdXRwdXQgZm9sZGVyLiBJdCBkaXNwbGF5cyB0aGUgc3Vic2V0IHNlbGVjdGlvbiBvZiByZXNpZHVhbCBwb29scywgdGhlIHNhZ2l0dGFsIGFyZWEgb2YgZWFjaCBwb29sLCB0aGUgbWF4aW11bSByZXNpZHVhbCBkZXB0aCAoZGVlcGVzdCBwb2ludCBwZXIgcG9vbCBhdCB6ZXJvIGZsb3cpLCBhbmQgdGhlIHBvb2wgbGVuZ3RoIG9mIGVhY2ggcG9vbC4gV2hlbiBjb25zaWRlcmVkIGF0IHRoZSByZWFjaC1zY2FsZSwgc3VtbWFyeSBzdGF0aXN0aWNzIG9mIHRoZSBtYXhpbXVtIHJlc2lkdWFsIGRlcHRoIGFuZCBwb29sIGxlbmd0aCBoYXZlIGJlZW4gY29uc2lkZXJlZCB1c2VmdWwgbWV0cmljcyB0byB0cmFjayBwb29sIHF1YWxpdHkgYW5kIHF1YW50aXR5IChlLmcuLCBMaXNsZSAxOTg2LCBNb3Nzb3AgYW5kIEJyYWRmb3JkIDIwMDYsIENsYXJrIGV0IGFsIDIwMTkpLg0KDQpUaGUgcmVhY2ggbWVhbiBvZiB0aGUgcG9vbCBtYXhpbXVtIHJlc2lkdWFsIGRlcHRocyBoYXMgYmVlbiB1c2VkIGFzIGEgcHJveHkgZm9yIHBvb2wgcXVhbGl0eSwgYW5kIHBvc2l0aXZlIHJlbGF0aW9uc2hpcHMgd2l0aCBDaGlub29rIHNhbG1vbiBkZW5zaXR5IGhhdmUgYmVlbiBkZW1vbnN0cmF0ZWQgKGUuZy4sIE1vc3NvcCBhbmQgQnJhZGZvcmQgMjAwNikuIFJlbGF0aW9uc2hpcHMgYmV0d2VlbiBoYWJpdGF0IG1ldHJpY3MgYW5kIGJpb3RhIGNhbiBiZSBoaWdobHkgY29udGV4dC1kZXBlbmRlbnQsIGFuZCBpbmRlcGVuZGVudCB2ZXJpZmljYXRpb24gaXMgcmVjb21tZW5kZWQgd2hlcmUgcG9zc2libGUuIEhvd2V2ZXIsIGFzIHRoZSByZXNvdXJjZXMgcmVxdWlyZWQgdG8gdGVzdCB0aGVzZSBhc3N1bXB0aW9ucyBhcmUgb2Z0ZW4gcHJvaGliaXRpdmUsIHdlIHJlY29tbWVuZCB0YWtpbmcgYWR2YW50YWdlIG9mIHJlbGF0aW9uc2hpcHMgdGhhdCBoYXZlIGFscmVhZHkgYmVlbiBxdWFudGl0YXRpdmVseSBkZW1vbnN0cmF0ZWQgaW4gdGhlIHNjaWVudGlmaWMgbGl0ZXJhdHVyZS4gQWx0aG91Z2ggaXQgKmlzKiBwb3NzaWJsZSB0byBnZW5lcmF0ZSBxdWFudGl0YXRpdmUgZXN0aW1hdGVzIG9mIGJpb3RpYyBkZW5zaXRpZXMgaWYgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGhhYml0YXQgbWV0cmljIGFuZCBiaW90aWMgZGVuc2l0eSBpcyBtb25vdG9uaWMsIHdlIGZlZWwgdGhhdCB0aGlzIGlzIHRvbyBzcGVjdWxhdGl2ZSB3aXRob3V0IGRhdGEgZm9yIHlvdXIgaW5kaXZpZHVhbCBzeXN0ZW0uIEhvd2V2ZXIsIGZvciB0aGUgcHVycG9zZSBvZiByZXN0b3JhdGlvbiBtb25pdG9yaW5nLCB3ZSBmZWVsIGl0IGlzIGluY3JlZGlibHkgcG93ZXJmdWwgdG8gYmUgYWJsZSB0byBkZW1vbnN0cmF0ZSAoZS5nLikgdGhhdCB3ZSBoYXZlIGNhdXNlZCBhbiAqeCotc2l6ZWQgaW5jcmVhc2UgaW4gYSBoYWJpdGF0IG1ldHJpYyB0aGF0IGlzIGtub3duIHRvIGJlIHBvc2l0aXZlbHkgY29ycmVsYXRlZCB3aXRoIHRhcmdldCBzcGVjaWVzIGRlbnNpdHkgaW4gYSBzaW1pbGFyIHN5c3RlbS4gDQoNClRoZSBwcm9wb3J0aW9uYWwgbGVuZ3RoIG9mIHBvb2xzIGluIHRoZSByZWFjaCBhbHNvIGhhcyBkZW1vbnN0cmF0ZWQgcG9zaXRpdmUgcmVsYXRpb25zaGlwcyB3aXRoIGNvaG8sIENoaW5vb2sgZGVuc2l0aWVzIChDbGFyayBldCBhbCAyMDE5KS4gQmVhciBpbiBtaW5kIHRoYXQgdGhlcmUgd2lsbCBhbHdheXMgYmUgbnVhbmNlIGludm9sdmVkIGluIHRoZSBhcHBsaWNhdGlvbiBhbmQgaW50ZXJwcmV0YXRpb24gb2YgaGFiaXRhdCBtZXRyaWNzLiBZb3UgbXVzdCB1bmRlcnN0YW5kIGFuZCBwcmVkaWN0LCBpbiBhbiAqYSBwcmlvcmkqIGZhc2hpb24sIHdoYXQgeW91ciByZXN0b3JhdGlvbiBvYmplY3RpdmVzIGFyZSB3aXRoIHJlc3BlY3QgdG8gaGFiaXRhdDogRG9lcyB5b3VyIHJlYWNoIG5lZWQgbW9yZSBwb29sIG9mIGEgY2VydGFpbiBkZXB0aD8gSXMgeW91ciByZWFjaCBsYWNraW5nIG11Y2gtbmVlZGVkIHJpZmZsZXM/IFByZXN1bWFibHkgdGhlcmUgYXJlIGNhc2VzIHdoZXJlIHRoZSByZWFjaCBoYXMgdG9vIG11Y2ggcG9vbCBoYWJpdGF0LiBUaGVzZSB0eXBlcyBvZiBxdWVzdGlvbnMgYXJlIGJlc3QgYWRkcmVzc2VkIHdpdGggd2VsbC1tYXRjaGVkIHJlZmVyZW5jZSBzaXRlcywgYnV0IGxvY2FsIGtub3dsZWRnZSBhbmQgdGhlIHNjaWVudGlmaWMgbGl0ZXJhdHVyZSB3aWxsIGFsc28gYmUgb2YgZ3JlYXQgaGVscC4NCg0KV2Ugd2lsbCBub3cgZ2VuZXJhdGUgYW5kIGV4cG9ydCB0byB5b3VyIG91dHB1dCBmb2xkZXIgc29tZSBzdW1tYXJ5IHN0YXRpc3RpY3MsIGluY2x1ZGluZyB0aGUgYWZvcmVtZW50aW9uZWQgbWVhbiBtYXggcmVzaWR1YWwgZGVwdGggYW5kIGxlbmd0aCBpbiByZXNpZHVhbCBwb29sLCBmb3IgeW91ciBkYXRhOg0KDQpgYGB7ciByZXNpZHVhbCBwb29sIHN1bW1hcnkgc3RhdHMsIGVjaG8gPSBGQUxTRX0NCiMgRnVuY3Rpb24gdG8gY2FsY3VsYXRlIHN1bW1hcnkgc3RhdGlzdGljcyBmb3IgdGhlIHN1YnNldCBvZiBwb29scywgZ3JvdXBlZCBieSBTaXRlIGFuZCBZZWFyDQpjYWxjdWxhdGVfc3Vic2V0X3N1bW1hcnkgPC0gZnVuY3Rpb24ocG9vbF9zdW1tYXJ5X2RmLCByZXNpZHVhbHMuZGYpIHsNCiAgIyBJbml0aWFsaXplIGEgbGlzdCB0byBzdG9yZSB0aGUgcmVzdWx0cyBmb3IgZWFjaCBTaXRlLVllYXIgY29tYmluYXRpb24NCiAgc3Vic2V0X3N1bW1hcnlfbGlzdCA8LSBsaXN0KCkNCiAgDQogICMgR3JvdXAgdGhlIHBvb2wgc3VtbWFyeSBkYXRhZnJhbWUgYnkgU2l0ZSBhbmQgWWVhcg0KICBwb29sX3N1bW1hcnlfZ3JvdXBlZCA8LSBzcGxpdChwb29sX3N1bW1hcnlfZGYsIGxpc3QocG9vbF9zdW1tYXJ5X2RmJFNpdGUsIHBvb2xfc3VtbWFyeV9kZiR5ZWFyKSkNCiAgDQogICMgSXRlcmF0ZSBvdmVyIGVhY2ggU2l0ZS1ZZWFyIGdyb3VwDQogIGZvciAoZ3JvdXBfbmFtZSBpbiBuYW1lcyhwb29sX3N1bW1hcnlfZ3JvdXBlZCkpIHsNCiAgICBncm91cCA8LSBwb29sX3N1bW1hcnlfZ3JvdXBlZFtbZ3JvdXBfbmFtZV1dDQogICAgDQogICAgIyBFbnN1cmUgdGhlIGdyb3VwIGhhcyB2YWxpZCBgU2l0ZWAgYW5kIGB5ZWFyYCB2YWx1ZXMNCiAgICBzaXRlIDwtIHVuaXF1ZShncm91cCRTaXRlKQ0KICAgIHllYXIgPC0gdW5pcXVlKGdyb3VwJHllYXIpDQogICAgDQogICAgaWYgKGxlbmd0aChzaXRlKSAhPSAxIHx8IGxlbmd0aCh5ZWFyKSAhPSAxKSB7DQogICAgICB3YXJuaW5nKHNwcmludGYoIlNraXBwaW5nIGdyb3VwICclcycgZHVlIHRvIGluY29uc2lzdGVudCBTaXRlIG9yIFllYXIuIiwgZ3JvdXBfbmFtZSkpDQogICAgICBuZXh0DQogICAgfQ0KICAgIA0KICAgICMgQ2FsY3VsYXRlIHRvdGFsIHNhZ2l0dGFsIGFyZWEgZm9yIHRoZSBzdWJzZXQgb2YgcG9vbHMgaW4gdGhpcyBncm91cA0KICAgIHRvdGFsX3NhZ2l0dGFsX2FyZWEgPC0gc3VtKGdyb3VwJHNhZ2l0dGFsX2FyZWEsIG5hLnJtID0gVFJVRSkNCiAgICANCiAgICAjIENhbGN1bGF0ZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gb2Ygc2FnaXR0YWwgYXJlYSBmb3IgdGhlIHN1YnNldCBvZiBwb29scyBpbiB0aGlzIGdyb3VwDQogICAgbWVhbl9zYWdpdHRhbF9hcmVhIDwtIG1lYW4oZ3JvdXAkc2FnaXR0YWxfYXJlYSwgbmEucm0gPSBUUlVFKQ0KICAgIHNkX3NhZ2l0dGFsX2FyZWEgPC0gc2QoZ3JvdXAkc2FnaXR0YWxfYXJlYSwgbmEucm0gPSBUUlVFKQ0KICAgIA0KICAgICMgQ2FsY3VsYXRlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBtYXhpbXVtIHJlc2lkdWFsIGRlcHRoIGZvciB0aGUgc3Vic2V0IG9mIHBvb2xzDQogICAgbWVhbl9tYXhfcmVzaWR1YWxfZGVwdGggPC0gbWVhbihncm91cCRtYXhfcmVzaWR1YWxfZGVwdGgsIG5hLnJtID0gVFJVRSkNCiAgICBzZF9tYXhfcmVzaWR1YWxfZGVwdGggPC0gc2QoZ3JvdXAkbWF4X3Jlc2lkdWFsX2RlcHRoLCBuYS5ybSA9IFRSVUUpDQogICAgDQogICAgIyBTdWJzZXQgdGhlIHJlc2lkdWFscy5kZiBmb3IgdGhlIGN1cnJlbnQgU2l0ZS1ZZWFyIGdyb3VwIHRvIGdldCB0aGUgdG90YWwgcmVhY2ggbGVuZ3RoDQogICAgZ3JvdXBfcmVzaWR1YWxzLmRmIDwtIHJlc2lkdWFscy5kZltyZXNpZHVhbHMuZGYkU2l0ZSA9PSBzaXRlICYgcmVzaWR1YWxzLmRmJHllYXIgPT0geWVhciwgXQ0KICAgIA0KICAgIGlmIChucm93KGdyb3VwX3Jlc2lkdWFscy5kZikgPT0gMCkgew0KICAgICAgd2FybmluZyhzcHJpbnRmKCJObyBtYXRjaGluZyByb3dzIGluIHJlc2lkdWFscy5kZiBmb3IgU2l0ZSAnJXMnIGFuZCBZZWFyICclcycuIiwgc2l0ZSwgeWVhcikpDQogICAgICBuZXh0DQogICAgfQ0KICAgIA0KICAgICMgQ2FsY3VsYXRlIHRoZSBwcm9wb3J0aW9uIG9mIHJlYWNoIGxlbmd0aCBpbiByZXNpZHVhbCBwb29scyBmb3IgdGhpcyBncm91cA0KICAgIHRvdGFsX3Bvb2xfbGVuZ3RoIDwtIHN1bShncm91cCRwb29sX2xlbmd0aCwgbmEucm0gPSBUUlVFKQ0KICAgIHRvdGFsX3JlYWNoX2xlbmd0aCA8LSBtYXgoZ3JvdXBfcmVzaWR1YWxzLmRmJGRpc3RhbmNlLCBuYS5ybSA9IFRSVUUpDQogICAgcHJvcG9ydGlvbl9sZW5ndGhfaW5fcmVzaWR1YWxfcG9vbCA8LSB0b3RhbF9wb29sX2xlbmd0aCAvIHRvdGFsX3JlYWNoX2xlbmd0aA0KICAgIA0KICAgICMgQ3JlYXRlIGEgc3VtbWFyeSB0YWJsZSBmb3IgdGhpcyBncm91cA0KICAgIHN1YnNldF9zdW1tYXJ5IDwtIGRhdGEuZnJhbWUoDQogICAgICBTaXRlID0gc2l0ZSwNCiAgICAgIFllYXIgPSB5ZWFyLA0KICAgICAgdG90YWxfc2FnaXR0YWxfYXJlYSA9IHRvdGFsX3NhZ2l0dGFsX2FyZWEsDQogICAgICBtZWFuX3NhZ2l0dGFsX2FyZWEgPSBtZWFuX3NhZ2l0dGFsX2FyZWEsDQogICAgICBzZF9zYWdpdHRhbF9hcmVhID0gc2Rfc2FnaXR0YWxfYXJlYSwNCiAgICAgIG1lYW5fbWF4X3Jlc2lkdWFsX2RlcHRoID0gbWVhbl9tYXhfcmVzaWR1YWxfZGVwdGgsDQogICAgICBzZF9tYXhfcmVzaWR1YWxfZGVwdGggPSBzZF9tYXhfcmVzaWR1YWxfZGVwdGgsDQogICAgICBwcm9wb3J0aW9uX2xlbmd0aF9pbl9yZXNpZHVhbF9wb29sID0gcHJvcG9ydGlvbl9sZW5ndGhfaW5fcmVzaWR1YWxfcG9vbA0KICAgICkNCiAgICANCiAgICAjIEFwcGVuZCB0aGUgc3VtbWFyeSBmb3IgdGhlIGN1cnJlbnQgU2l0ZS1ZZWFyIGNvbWJpbmF0aW9uIHRvIHRoZSBsaXN0DQogICAgc3Vic2V0X3N1bW1hcnlfbGlzdFtbZ3JvdXBfbmFtZV1dIDwtIHN1YnNldF9zdW1tYXJ5DQogIH0NCiAgDQogICMgQ29tYmluZSB0aGUgcmVzdWx0cyBmcm9tIGFsbCBTaXRlLVllYXIgZ3JvdXBzIGludG8gYSBzaW5nbGUgZGF0YWZyYW1lDQogIGZpbmFsX3N1YnNldF9zdW1tYXJ5X2RmIDwtIGRvLmNhbGwocmJpbmQsIHN1YnNldF9zdW1tYXJ5X2xpc3QpDQogIA0KICByZXR1cm4oZmluYWxfc3Vic2V0X3N1bW1hcnlfZGYpDQp9DQoNCnN1YnNldF9zdW1tYXJ5X3Jlc3VsdCA8LSBjYWxjdWxhdGVfc3Vic2V0X3N1bW1hcnkocG9vbF9zdW1tYXJ5X3Jlc3VsdCwgcmVzaWR1YWxzLmRmKQ0KDQojIERpc3BsYXkgdGhlIHJlc3VsdCBhcyBhIHRhYmxlDQpzdWJzZXRfc3VtbWFyeV9yZXN1bHQgPC0gc3Vic2V0X3N1bW1hcnlfcmVzdWx0ICU+JQ0KICBzZWxlY3QoU2l0ZSwgWWVhciwgZXZlcnl0aGluZygpKSAgIyBNb3ZlIFNpdGUgYW5kIFllYXIgdG8gdGhlIGxlZnQNCmRhdGF0YWJsZSgNCiAgc3Vic2V0X3N1bW1hcnlfcmVzdWx0LA0KICBjYXB0aW9uID0gIlJlYWNoIFN1bW1hcnkgU3RhdGlzdGljcyBmb3IgUG9vbHMgYnkgU2l0ZSBhbmQgWWVhciIsDQogIHJvd25hbWVzID0gRkFMU0UsICAjIEhpZGUgcm93IG51bWJlcnMNCiAgb3B0aW9ucyA9IGxpc3QoDQogICAgcGFnZUxlbmd0aCA9IDEwLCAgIyBOdW1iZXIgb2Ygcm93cyBwZXIgcGFnZQ0KICAgIGF1dG9XaWR0aCA9IFRSVUUNCiAgKQ0KKSU+JQ0KICBmb3JtYXRSb3VuZChjb2x1bW5zID0gbmFtZXMoc3Vic2V0X3N1bW1hcnlfcmVzdWx0KVtzYXBwbHkoc3Vic2V0X3N1bW1hcnlfcmVzdWx0LCBpcy5udW1lcmljKV0sIGRpZ2l0cyA9IDMpDQoNCiMgRXhwb3J0IHRhYmxlDQpleHBvcnRfdGFibGUoYXMuZGF0YS5mcmFtZShzdWJzZXRfc3VtbWFyeV9yZXN1bHQpLCAiUmVhY2ggU3VtbWFyeSBTdGF0cyBmb3IgUG9vbHMgYnkgU2l0ZSBhbmQgWWVhci5jc3YiKQ0KYGBgDQpUaGVzZSBhYm92ZSBzdGF0aXN0aWNzIHNob3VsZCBiZSB1c2VmdWwgZm9yIHRyYWNraW5nIGNoYW5nZXMgb3ZlciB0aW1lLCBvciBjb21wYXJpbmcgcmVmZXJlbmNlIC8gY29udHJvbCByZWFjaGVzLiBCZWNhdXNlIHRoZXkgYXJlIGFsbCBiYXNlZCBvbiByZXNpZHVhbCBkZXB0aHMsIHRoZXkgYXJlIGZsb3ctaW5kZXBlbmRlbnQuIA0KDQpUb3RhbCBzYWdpdHRhbCBhcmVhIGFuZCBwcm9wb3J0aW9uIG9mIHRoZSByZWFjaCBsZW5ndGggaW4gcmVzaWR1YWwgcG9vbCBzaG91bGQgYmUgY29tcGFyZWQgYmV0d2VlbiB5ZWFycyBhbmQvb3Igc2l0ZXMsIGFuZCB5b3UgY2FuIGludGVycHJldCB3aGV0aGVyIHRoZSBjaGFuZ2VzIGFyZSBpbiB0aGUgcHJlZGljdGVkIGRpcmVjdGlvbiBhbmQgb2YgYSBtZWFuaW5nZnVsIG1hZ25pdHVkZS4gU2luY2UgdGhlc2UgdHdvIG1ldHJpY3MgaGF2ZSBvbmUgdmFsdWUgcGVyIHJlYWNoLCB0aGUgbWV0cmljcyB0aGVtc2VsdmVzIGNhbm5vdCBiZSBldmFsdWF0ZWQgc3RhdGlzdGljYWxseSAodW5sZXNzIHlvdSBoYXZlIGEgbGFyZ2UgbnVtYmVyIG9mIHJlYWNoZXMveWVhcnMpLCBob3dldmVyIGEgZGlyZWN0aW9uYWwgY2hhbmdlIG92ZXIgdGltZSB0aGF0IGFsaWducyB3aXRoIHlvdXIgcHJlZGljdGlvbnMgaXMgb2J2aW91c2x5IHF1aXRlIGEgZ29vZCBzaWduLiANCg0KIyMgSW5mZXJlbnRpYWwgVGVzdHMNCg0KV2UgY2FuIGFwcGx5IGluZmVyZW50aWFsIHN0YXRpc3RpY2FsIHRlc3RzIHRvIHRoZSBzYWdpdHRhbCBhcmVhLCBtYXhpbXVtIHBvb2wgZGVwdGgsIGFuZCBwb29sIGxlbmd0aCBkYXRhIC0gdGhhdCBpcywgdGhlIGRhdGEgd2hpY2ggaGF2ZSB2YWx1ZXMgYXQgdGhlIGxldmVsIG9mIGVhY2ggcG9vbCAoaS5lLiwgYSBwb3B1bGF0aW9uIG9mIHZhbHVlcyBpcyBhdmFpbGFibGUgcGVyIHJlYWNoL3llYXIpLiBXZSB3aWxsIHVzZSBpbmZlcmVudGlhbCBzdGF0aXN0aWNhbCB0ZXN0cyB0byBkZXRlcm1pbmUgd2hldGhlciB0aGUgZGlmZmVyZW5jZXMgd2Ugb2JzZXJ2ZWQgYW1vbmcgcmVhY2hlcyBhbmQgeWVhcnMgYXJlIGxpa2VseSB0byBiZSBkdWUgdG8gY2hhbmNlLiBZb3Ugd2lsbCBiZSBmYW1pbGlhciB3aXRoIHAgdmFsdWVzIG9mIDAuMDUgKG9ic2VydmVkIHJlc3VsdCBleHBlY3RlZCBqdXN0IGR1ZSB0byBjaGFuY2UgMSBpbiAyMCB0aW1lcykgYW5kIHdlIHdpbGwgdXNlIHA9MC4wNSBhcyBvdXIgY3V0LW9mZiBoZXJlLiBIb3dldmVyLCBkZXBlbmRpbmcgb24geW91ciBhZGFwdGl2ZSBtYW5hZ2VtZW50IHBsYW5zLCB5b3UgbWF5IGJlIHdpbGxpbmcgdG8gYWNjZXB0IGRpZmZlcmVudCBsZXZlbHMgb2YgY2VydGFpbnR5LCBhbmQgcCB2YWx1ZXMgb2YgMC4xIGFyZSBub3QgdW5oZWFyZCBvZiBpbiByZXN0b3JhdGlvbiBwcm9qZWN0cy4gVGhpcyBhbGwgZGVwZW5kcyBvbiB0aGUgcmlzayB0b2xlcmFuY2Ugb2YgeW91IGFuZCB5b3VyIHRlYW0sIGFuZCBzaG91bGQgYmUgZXN0YWJsaXNoZWQgYmVmb3JlIGNvbmR1Y3RpbmcgYW5hbHlzZXMuDQoNCkZvciB0aGVzZSBpbmZlcmVudGlhbCB0ZXN0cyB3ZSB3aWxsIHVzZSBBTk9WQXMgYmVjYXVzZSBvZiB0aGVpciBmYW1pbGlhcml0eSBmb3IgZWNvbG9naXN0cyBhbmQgZXhwZWN0ZWQgc3VpdGFiaWxpdHkgZm9yIHRoZSBkYXRhLiBGb3IgdGhlIG1ldHJpY3MgcmVsYXRpbmcgdG8gcmVzaWR1YWwgcG9vbHMgdGhhdCB3ZSBoYXZlIGdlbmVyYXRlZCwgd2Ugd2lsbCB0ZXN0IGZvciBkaWZmZXJlbmNlcyBiZXR3ZWVuIHNpdGVzLCB5ZWFycywgYW5kIGFuIGludGVyYWN0aW9uIG9mIHNpdGVzKnllYXJzIChpLmUuLCBkaWQgdGhlIGRpZmZlcmVudCBsb2NhdGlvbnMgY2hhbmdlIGRpZmZlcmVudGx5IG92ZXIgdGltZSkuIFRoZSBjb2RlIHVzZXMgdGhlIHN1YnNldCBvZiBwb29scyB0aGF0IHdlcmUgZGVmaW5lZCBlYXJsaWVyIGFzICdtZWFuaW5nZnVsJy4NCg0KKipDaG9pY2Ugb2YgTWV0cmljKio6IEF0IHRoaXMgcG9pbnQsIHlvdSBzaG91bGQgY2hvb3NlIHdoaWNoIG9mICdzYWdpdHRhbCBhcmVhJywgJ21heGltdW0gcG9vbCBkZXB0aCcsIGFuZCAncG9vbCBsZW5ndGgnIGJlc3QgYWxpZ25zIHdpdGggeW91ciBuZWVkcyAoZS5nLiwgcmVsZXZhbmNlIHRvIHJlc3RvcmF0aW9uIG9iamVjdGl2ZSwgY29tcGFyaXNvbnMgd2l0aCBsaXRlcmF0dXJlLCBlYXNlIG9mIGNvbW11bmljYXRpb24pLiBZb3Ugd2lsbCBiYXNlIHlvdXIgaW50ZXJwcmV0YXRpb24gb2YgdGhlIEFOT1ZBIG9uIHRoaXMgY2hvc2VuIG1ldHJpYywgZXZlbiB0aG91Z2ggd2Ugd2lsbCBydW4gQU5PVkEgZm9yIGFsbCB0aHJlZS4gDQoNClRoZSByZWFzb24gZm9yIHNlbGVjdGluZyBvbmUgbWV0cmljIGZvciBpbnRlcnByZXRpbmcgeW91ciBoeXBvdGhlc2lzIGlzIHRoYXQgdGhlIG1ldHJpY3MgYXJlIG5vdCBpbmRlcGVuZGVudCBvZiBvbmUgYW5vdGhlcjogU2FnaXR0YWwgYXJlYSBpbmNvcnBvcmF0ZXMgZGVwdGggYW5kIGxlbmd0aCBjb21wb25lbnRzLCBhbmQgYWxsIHRocmVlIG1ldHJpY3MgYXJlIGNvbm5lY3RlZCBpbiB0aGUgc3RyZWFtOyBpZiB5b3UgdXNlZCBhIHN1YnNldCBvZiB0aGUgcmVzaWR1YWwgcG9vbHMsIGFsbCBtZXRyaWNzIGluaGVyZW50bHkgaW5jbHVkZSBzb21lIGluZm9ybWF0aW9uIGFib3V0IGRlcHRoLiBJZiB5b3Ugd2VyZSB0byBjb250aW51ZSB3aXRob3V0IGRlY2lkaW5nIHVwb24gYSBtZXRyaWMsIGl0IHdvdWxkIGJlIHRvbyB0ZW1wdGluZyB0byBjb21lIHVwIHdpdGggcG9zdC1ob2MgZXhwbGFuYXRpb25zIChlLmcuLCBpZiBzYWdpdHRhbCBhcmVhIGluY3JlYXNlZCBidXQgbm90IGRlcHRoIG9yIGxlbmd0aCkuIFlvdSBzaG91bGQgY2VydGFpbmx5IGNvbnNpZGVyIHBvdGVudGlhbCBpbXBsaWNhdGlvbnMgb2YgeW91ciByZXN1bHRzIChjYXJlZnVsbHkpLCBidXQgaW4gdGVybXMgb2YgZXZhbHVhdGluZyB0aGUgc3VjY2VzcyBvZiB5b3VyIHByb2plY3QsIGl0IGlzIGltcG9ydGFudCB0aGF0IHlvdSBkZWNpZGUgaW4gYWR2YW5jZSB3aGljaCBtZXRyaWMgY2hhbmdlID0gc3VjY2Vzcy4NCg0KQWx0aG91Z2ggaXQgbWF5IGJlIHBvc3NpYmxlIHRvIHJ1biBhIE1BTk9WQSB0ZXN0ICh3aGljaCBjYW4gYWNjb21tb2RhdGUgY29ycmVsYXRlZCBkZXBlbmRlbnQgdmFyaWFibGVzKSB1c2luZyBhbGwgdGhyZWUgbWV0cmljcyB0b2dldGhlciwgTUFOT1ZBIHRlc3RzIHR5cGljYWxseSByZXF1aXJlIGxhcmdlciBzYW1wbGUgc2l6ZXMgdGhhbiB3ZSBhbnRpY2lwYXRlIGZvciBtYW55IHJlYWNoIHN1cnZleXMuIFRoZXJlZm9yZSwgd2Ugc3RpY2sgd2l0aCBtdWx0aXBsZSBBTk9WQXMgd2l0aCBhIGxhcmdlIGRvc2Ugb2YgY2F1dGlvbi4NCg0KIyMjIEFzc3VtcHRpb24gUm9idXN0bmVzcw0KDQpXaGVuZXZlciBhcHBseWluZyBzdGF0aXN0aWNhbCB0ZXN0cywgd2Ugc2hvdWxkIGVuc3VyZSB0aGF0IG91ciBkYXRhIGlzIHN1aXRhYmxlLCBpbiB0aGF0IGl0IG1lZXRzIHRoZSBhc3N1bXB0aW9ucyBvZiB0aGUgaW50ZW5kZWQgaW5mZXJlbnRpYWwgdGVzdC4gRm9yIEFOT1ZBcyB0aGUgYXNzdW1wdGlvbnMgYXJlOg0KDQotIERhdGEgaW4gZGlmZmVyZW50IGdyb3VwcyBzaG91bGQgYmUgaW5kZXBlbmRlbnQ6IA0KDQogIC0gT25lIG9mIHlvdXIgc2l0ZXMgbXVzdCBub3QgY2F1c2UgY2hhbmdlcyBpbiBhbm90aGVyICh0aG91Z2ggYm90aCBzaXRlcyBleHBlcmllbmNpbmcgc2hhcmVkICdleHRlcm5hbCcgY2F1c2FsIGZhY3RvcnMsIHN1Y2ggYXMgYmVpbmcgaW4gdGhlIHNhbWUgd2F0ZXJzaGVkLCBpcyBhY2NlcHRhYmxlKS4gVGhpcyBpcyBob3BlZnVsbHkgYWNjb3VudGVkIGZvciBieSBnb29kIHNlbGVjdGlvbiBvZiBpbXBhY3QvY29udHJvbC9yZWZlcmVuY2Ugc2l0ZXMuIA0KICANCiAgLSBZb3UgbWF5IG5vdGUgdGhhdCBubyBzaXRlIGlzIGFjdHVhbGx5IGluZGVwZW5kZW50IGZyb20gdGhhdCBzYW1lIHNpdGUgaW4gdGhlIHBhc3QuIEZvciBsb25nZXIgdGltZS1zZXJpZXMgd2Ugd291bGQgbmVlZCB0byBhZG9wdCBhIGRpZmZlcmVudCBpbmZlcmVudGlhbCBhcHByb2FjaCB0byBhdm9pZCBhdXRvY29ycmVsYXRpb24sIGJ1dCBoZXJlIHdlIGFyZSBkZWFsaW5nIHdpdGggc2ltcGxlIGJlZm9yZSB2cyBhZnRlciBjb21wYXJpc29ucywgYW5kIGl0IGlzIHdpZGVseSBhY2NlcHRlZCB0aGF0IEFOT1ZBcyBhcmUgc3VpdGFibGUgZm9yIGJlZm9yZS9hZnRlciBjb21wYXJpc29ucyBpZiB0aGUgY29tcGFyaXNvbiBpcyBiYWxhbmNlZCAoZS5nLiwgMiB5ZWFycyBvZiBiZWZvcmUgZGF0YSBjb21wYXJlZCB3aXRoIDIgeWVhcnMgb2YgYWZ0ZXIgZGF0YSkuDQogIA0KLSBSZXNpZHVhbHMgYXJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkOiBJbiB0aGlzIGNhc2Ugd2UgbWVhbiByZXNpZHVhbHMgbW9yZSBicm9hZGx5IC0gdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBlYWNoIGRhdGFwb2ludCBhbmQgdGhlIG1lYW4uIFdlIHdpbGwgZXhhbWluZSB0aGlzIGFzc3VtcHRpb24gdXNpbmcgUS1RIHBsb3RzIGFuZCB0aGUgU2hhcGlyby1XaWxrIG5vcm1hbGl0eSB0ZXN0Lg0KDQotIEhvbW9zY2VkYXN0aWNpdHk6IFZhcmlhbmNlIHNob3VsZCBiZSBicm9hZGx5IGVxdWFsIGFjcm9zcyBhbGwgZ3JvdXBzLiBXZSB3aWxsIHRlc3QgdGhpcyB3aXRoIExldmVuZSdzIHRlc3QuDQoNCklmIGFueSBvZiB0aGVzZSBhc3N1bXB0aW9ucyBhcmUgdmlvbGF0ZWQsIHdlIGNhbiB0cmFuc2Zvcm0gdGhlIGRhdGEgYW5kIHRlc3Qgd2hldGhlciB0aGUgdHJhbnNmb3JtZWQgZGF0YSAobG9nLSwgYXJjc2luZS0gZXRjLikgc2F0aXNmaWVzIHRoZSBhc3N1bXB0aW9ucy4gSWYgdGhpcyBpcyBub3QgYW4gb3B0aW9uLCB3ZSBzaG91bGQgc2VlayBhIG1vcmUgc3VpdGFibGUgc3RhdGlzdGljYWwgdGVzdCAoZS5nLiBXZWxjaCdzIEFOT1ZBIG9yIG1peGVkLWVmZmVjdHMgbW9kZWxzKS4gDQoNClRoZSB0ZXN0cyBvZiBhc3N1bXB0aW9ucyBhcmUgY2FycmllZCBvdXQgYmVsb3csIGFmdGVyIHdlIHNwZWNpZnkgdGhlIGJlZm9yZSBhbmQgYWZ0ZXIgZGF0YSB0aGF0IHlvdSB3aXNoIHRvIGNvbXBhcmUuDQoNCiMjIyMgQmVmb3JlIC8gQWZ0ZXIgWWVhcnMNCg0KRW50ZXIgeW91ciBiZWZvcmUgYW5kIGFmdGVyIHllYXJzIGluIHRoZSBiZWxvdyBjb2RlLCB5b3UgbWF5IGhhdmUgbW9yZSB0aGFuIG9uZSB5ZWFyIGluIGVhY2ggY2F0ZWdvcnkuIFJlbWVtYmVyIHRoYXQgdGhlc2Ugc2hvdWxkIGJhbGFuY2UgKGVxdWFsIG51bWJlciBvZiB5ZWFycyBiZWZvcmUgYXMgYWZ0ZXIpLCBidXQgdGhleSBuZWVkIG5vdCBiZSBjb25zZWN1dGl2ZSB5ZWFycy4gSWYgeW91IGRvIG5vdCBoYXZlIGJhbGFuY2VkIGRhdGEgKGUuZy4sIG9ubHkgb25lIHllYXIgd2FzIHBvc3NpYmxlIGJlZm9yZSBwcm9qZWN0IGltcGxlbWVudGF0aW9uKSBiZSB2ZXJ5IGNhdXRpb3VzIGluIHJ1bm5pbmcgYW5kIGludGVycHJldGluZyBhbiBBTk9WQS4gWW91IGNvdWxkIHNlbGVjdCBvbmx5IGEgc3Vic2V0IG9mIHlvdXIgZGF0YSB0byBrZWVwIHRoZSBjb21wYXJpc29uIGJhbGFuY2VkLCBidXQgaWYgeW91IGRvIHRoaXMgZm9yIG1vcmUgdGhhbiBvbmUgc2V0IG9mIGRhdGVzIHlvdSBtdXN0IGFjY291bnQgZm9yIHRoZSBtdWx0aXBsZSBjb21wYXJpc29ucyBpbmZsYXRpbmcgdGhlIGxpa2VsaWhvb2Qgb2YgYSBUeXBlIEkgZXJyb3IgKGZhbHNlIHBvc2l0aXZlKS4NCg0KYGBge3IgZGVmaW5lIGJlZm9yZSBhZnRlcn0NCiMgRGVmaW5lICJCZWZvcmUiIGFuZCAiQWZ0ZXIiIHllYXJzDQpiZWZvcmVfeWVhcnMgPC0gYygyMDI0KSAjYWRkIG1vcmUgeWVhcnMgaW5zaWRlIGJyYWNrZXRzIGlmIG5lZWRlZCwgZS5nLiAnYygyMDI0LCAyMDI1LCAyMDI2KScNCmFmdGVyX3llYXJzIDwtIGMoMjAyNSkgI2FkZCBtb3JlIHllYXJzIGluc2lkZSBicmFja2V0cyBpZiBuZWVkZWQsIGUuZy4gJ2MoMjAyNywgMjAyOSwgMjAzNiknDQpgYGANCg0KYGBge3IgY2F0ZWdvcmlzZSBieSBiZWZvcmUgYWZ0ZXIsIGVjaG8gPSBGQUxTRX0NCiMgQ2F0ZWdvcml6ZSB5ZWFycw0KcG9vbF9zdW1tYXJ5X3Jlc3VsdCA8LSBwb29sX3N1bW1hcnlfcmVzdWx0ICU+JQ0KICBtdXRhdGUoVGltZV9DYXRlZ29yeSA9IGNhc2Vfd2hlbigNCiAgICB5ZWFyICVpbiUgYmVmb3JlX3llYXJzIH4gIkJlZm9yZSIsDQogICAgeWVhciAlaW4lIGFmdGVyX3llYXJzIH4gIkFmdGVyIiwNCiAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXw0KICApKQ0KYGBgDQoNClRoZSBuZXh0IHNlY3Rpb24gb2YgY29kZSBnZW5lcmF0ZXMgdGVzdHMgYW5kIGZpZ3VyZXMgdGhhdCB5b3Ugc2hvdWxkIHJldmlldyB0byBlbnN1cmUgeW91ciBkYXRhIGFyZSBzdWl0YWJsZSBmb3IgYW4gQU5PVkEuIEluIGJyaWVmLCBsb29rIGZvciB0aGUgZm9sbG93aW5nOg0KDQotIEJveHBsb3RzOiBjb25zaWRlciB3aGV0aGVyIG91dGxpZXJzIChkb3RzKSBhcmUgcmVhbCBvciBlcnJvcnMNCi0gUS1RIHBsb3RzOiBhIHJlYXNvbmFibHkgc3RyYWlnaHQgbGluZSBvZiBwb2ludHMgbWVhbnMgYWxpZ25tZW50IHdpdGggbm9ybWFsIGRpc3RyaWJ1dGlvbg0KLSBOb3JtYWxpdHkgdGVzdCAoU2hhcGlyby1XaWxrKTogcDwwLjA1IGluZGljYXRlcyBub24tbm9ybWFsaXR5DQotIExldmVuZSdzIHRlc3Q6IHA8MC4wNSBpbmRpY2F0ZXMgdGhhdCB2YXJpYW5jZSBhbW9uZyBncm91cHMgZGlmZmVycw0KLSBTa2V3bmVzcyB2YWx1ZXMgPCAwIGFyZSBsZWZ0IHNrZXdlZCwgPiAwIHJpZ2h0IHNrZXdlZC4gS3VydG9zaXMgdmFsdWVzIDwgMyBsaWdodC10YWlsZWQsID4gMyBoZWF2eS10YWlsZWQuDQoNCmBgYHtyIG5vcm1hbGl0eSBhc3N1bXB0aW9ucyBldGMsIGVjaG8gPSBGQUxTRX0NCiMgRmlsdGVyIG91dCBzaXRlcyB3aXRob3V0IGJvdGggdGltZSBjYXRlZ29yaWVzLiBSZW1vdmUgcm93cyB3aXRoIHBvb2xfaWQgPSAiVG90YWwiLiANCnBvb2xfc3VtbWFyeV9maWx0ZXJlZCA8LSBwb29sX3N1bW1hcnlfcmVzdWx0ICU+JQ0KICBmaWx0ZXIocG9vbF9pZCAhPSAiVG90YWwiKSAlPiUNCiAgZ3JvdXBfYnkoU2l0ZSkgJT4lDQogIGZpbHRlcihhbGwoYygiQmVmb3JlIiwgIkFmdGVyIikgJWluJSBUaW1lX0NhdGVnb3J5KSkgJT4lDQogIHVuZ3JvdXAoKQ0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIEZ1bmN0aW9uIHRvIGdlbmVyYXRlIGJveHBsb3RzLiBMb29rIG91dCBmb3Igb3V0bGllcnMNCmdlbmVyYXRlX2JveHBsb3RzIDwtIGZ1bmN0aW9uKHBvb2xfc3VtbWFyeV9kZikgew0KICB2YXJpYWJsZXMgPC0gYygic2FnaXR0YWxfYXJlYSIsICJtYXhfcmVzaWR1YWxfZGVwdGgiLCAicG9vbF9sZW5ndGgiKQ0KICBib3hwbG90c19saXN0IDwtIGxpc3QoKQ0KICANCiAgZm9yICh2YXIgaW4gdmFyaWFibGVzKSB7DQogICAgYm94cGxvdCA8LSBnZ3Bsb3QocG9vbF9zdW1tYXJ5X2RmLCBhZXMoeCA9IGludGVyYWN0aW9uKFNpdGUsIFRpbWVfQ2F0ZWdvcnkpLCB5ID0gLmRhdGFbW3Zhcl1dKSkgKw0KICAgICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJCb3hwbG90IG9mIiwgdmFyKSwgeCA9ICJTaXRlLVRpbWUgQ2F0ZWdvcnkiLCB5ID0gdmFyKSArDQogICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KICAgIGJveHBsb3RzX2xpc3RbW3Zhcl1dIDwtIGJveHBsb3QNCiAgfQ0KICByZXR1cm4oYm94cGxvdHNfbGlzdCkNCn0NCg0KIyBHZW5lcmF0ZSBib3hwbG90cw0KYm94cGxvdHMgPC0gZ2VuZXJhdGVfYm94cGxvdHMocG9vbF9zdW1tYXJ5X2ZpbHRlcmVkKQ0KDQojIERpc3BsYXkgYm94cGxvdHMNCmZvciAocGxvdCBpbiBib3hwbG90cykgew0KICBwcmludChwbG90KQ0KfSAjIExvb2sgb3V0IGZvciBvdXRsaWVycw0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyBGdW5jdGlvbiB0byBnZW5lcmF0ZSBRLVEgcGxvdHMuIExvb2sgZm9yIGRldmlhdGlvbnMgZnJvbSBsaW5lYXJpdHkNCmdlbmVyYXRlX3FxcGxvdHMgPC0gZnVuY3Rpb24ocG9vbF9zdW1tYXJ5X2RmKSB7DQogICMgQ3JlYXRlIGEgbGlzdCBvZiB2YXJpYWJsZXMgdG8gcGxvdA0KICB2YXJpYWJsZXMgPC0gYygic2FnaXR0YWxfYXJlYSIsICJtYXhfcmVzaWR1YWxfZGVwdGgiLCAicG9vbF9sZW5ndGgiKQ0KICANCiAgIyBJbml0aWFsaXplIGEgbGlzdCB0byBzdG9yZSB0aGUgUS1RIHBsb3RzDQogIHFxcGxvdHNfbGlzdCA8LSBsaXN0KCkNCiAgDQogICMgSXRlcmF0ZSBvdmVyIGVhY2ggdmFyaWFibGUNCiAgZm9yICh2YXIgaW4gdmFyaWFibGVzKSB7DQogICAgcXFwbG90IDwtIGdncGxvdChwb29sX3N1bW1hcnlfZGYsIGFlcyhzYW1wbGUgPSAuZGF0YVtbdmFyXV0pKSArICANCiAgICAgIHN0YXRfcXEoKSArDQogICAgICBzdGF0X3FxX2xpbmUoKSArDQogICAgICBsYWJzKHRpdGxlID0gcGFzdGUoIlEtUSBQbG90IG9mIiwgdmFyKSkgKw0KICAgICAgZmFjZXRfd3JhcCh+IGludGVyYWN0aW9uKFNpdGUsIHllYXIpKQ0KICAgIA0KICAgICMgQWRkIHRoZSBwbG90IHRvIHRoZSBsaXN0DQogICAgcXFwbG90c19saXN0W1t2YXJdXSA8LSBxcXBsb3QNCiAgfQ0KICANCiAgIyBSZXR1cm4gdGhlIGxpc3Qgb2YgUS1RIHBsb3RzDQogIHJldHVybihxcXBsb3RzX2xpc3QpDQp9DQoNCiMgR2VuZXJhdGUgUS1RIHBsb3RzDQpxcXBsb3RzIDwtIGdlbmVyYXRlX3FxcGxvdHMocG9vbF9zdW1tYXJ5X2ZpbHRlcmVkKQ0KDQojIERpc3BsYXkgUS1RIHBsb3RzDQpmb3IgKHBsb3QgaW4gcXFwbG90cykgew0KICBwcmludChwbG90KQ0KfSAgIyBMb29rIGZvciBkZXZpYXRpb25zIGZyb20gbGluZWFyaXR5DQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIEZ1bmN0aW9uIHRvIHRlc3QgZm9yIG5vcm1hbGl0eSANCnRlc3Rfbm9ybWFsaXR5IDwtIGZ1bmN0aW9uKHBvb2xfc3VtbWFyeV9kZikgew0KICBwb29sX3N1bW1hcnlfZ3JvdXBlZCA8LSBzcGxpdChwb29sX3N1bW1hcnlfZGYsIGxpc3QocG9vbF9zdW1tYXJ5X2RmJFNpdGUsIHBvb2xfc3VtbWFyeV9kZiRUaW1lX0NhdGVnb3J5KSkNCiAgbm9ybWFsaXR5X3Jlc3VsdHNfbGlzdCA8LSBsaXN0KCkNCiAgDQogIGZvciAoZ3JvdXBfbmFtZSBpbiBuYW1lcyhwb29sX3N1bW1hcnlfZ3JvdXBlZCkpIHsNCiAgICBncm91cCA8LSBwb29sX3N1bW1hcnlfZ3JvdXBlZFtbZ3JvdXBfbmFtZV1dDQogICAgaWYgKG5yb3coZ3JvdXApIDwgMykgew0KICAgICAgbm9ybWFsaXR5X3Jlc3VsdHNfbGlzdFtbZ3JvdXBfbmFtZV1dIDwtIGRhdGEuZnJhbWUoDQogICAgICAgIFNpdGUgPSBOQSwgVGltZV9DYXRlZ29yeSA9IE5BLA0KICAgICAgICBtYXhfcmVzaWR1YWxfZGVwdGhfcF92YWx1ZSA9IE5BLA0KICAgICAgICBzYWdpdHRhbF9hcmVhX3BfdmFsdWUgPSBOQSwNCiAgICAgICAgcG9vbF9sZW5ndGhfcF92YWx1ZSA9IE5BLA0KICAgICAgICBtZXNzYWdlID0gIk5vdCBlbm91Z2ggZGF0YSBmb3Igbm9ybWFsaXR5IHRlc3QiDQogICAgICApDQogICAgICBuZXh0DQogICAgfQ0KICAgIG1heF9yZXNpZHVhbF9kZXB0aF90ZXN0IDwtIHNoYXBpcm8udGVzdChncm91cCRtYXhfcmVzaWR1YWxfZGVwdGgpDQogICAgc2FnaXR0YWxfYXJlYV90ZXN0IDwtIHNoYXBpcm8udGVzdChncm91cCRzYWdpdHRhbF9hcmVhKQ0KICAgIHBvb2xfbGVuZ3RoX3Rlc3QgPC0gc2hhcGlyby50ZXN0KGdyb3VwJHBvb2xfbGVuZ3RoKQ0KICAgIA0KICAgIG5vcm1hbGl0eV9yZXN1bHRzX2xpc3RbW2dyb3VwX25hbWVdXSA8LSBkYXRhLmZyYW1lKA0KICAgICAgU2l0ZSA9IHVuaXF1ZShncm91cCRTaXRlKSwNCiAgICAgIFRpbWVfQ2F0ZWdvcnkgPSB1bmlxdWUoZ3JvdXAkVGltZV9DYXRlZ29yeSksDQogICAgICBtYXhfcmVzaWR1YWxfZGVwdGhfcF92YWx1ZSA9IG1heF9yZXNpZHVhbF9kZXB0aF90ZXN0JHAudmFsdWUsDQogICAgICBzYWdpdHRhbF9hcmVhX3BfdmFsdWUgPSBzYWdpdHRhbF9hcmVhX3Rlc3QkcC52YWx1ZSwNCiAgICAgIHBvb2xfbGVuZ3RoX3BfdmFsdWUgPSBwb29sX2xlbmd0aF90ZXN0JHAudmFsdWUsDQogICAgICBtZXNzYWdlID0gIk5vcm1hbGl0eSB0ZXN0IGNvbXBsZXRlZCINCiAgICApDQogIH0NCiAgbm9ybWFsaXR5X3Jlc3VsdHNfZGYgPC0gZG8uY2FsbChyYmluZCwgbm9ybWFsaXR5X3Jlc3VsdHNfbGlzdCkNCiAgcmV0dXJuKG5vcm1hbGl0eV9yZXN1bHRzX2RmKQ0KfQ0KDQpub3JtYWxpdHlfcmVzdWx0cyA8LSB0ZXN0X25vcm1hbGl0eShwb29sX3N1bW1hcnlfZmlsdGVyZWQpDQoNCm5vcm1hbGl0eV9yZXN1bHRzICU+JQ0KICBtdXRhdGUoDQogICAgbWF4X3Jlc2lkdWFsX2RlcHRoX3BfdmFsdWUgPSByb3VuZChtYXhfcmVzaWR1YWxfZGVwdGhfcF92YWx1ZSwgMyksDQogICAgc2FnaXR0YWxfYXJlYV9wX3ZhbHVlID0gcm91bmQoc2FnaXR0YWxfYXJlYV9wX3ZhbHVlLCAzKSwNCiAgICBwb29sX2xlbmd0aF9wX3ZhbHVlID0gcm91bmQocG9vbF9sZW5ndGhfcF92YWx1ZSwgMykNCiAgKSAlPiUNCiAga2FibGUoDQogICAgY2FwdGlvbiA9ICJOb3JtYWxpdHkgVGVzdCBSZXN1bHRzIGZvciBQb29sIFN1bW1hcnkgRGF0YSIsDQogICAgY29sLm5hbWVzID0gYygiU2l0ZSIsICJUaW1lIENhdGVnb3J5IiwgDQogICAgICAgICAgICAgICAgICAiTWF4IFJlc2lkdWFsIERlcHRoIFAtVmFsdWUiLCANCiAgICAgICAgICAgICAgICAgICJTYWdpdHRhbCBBcmVhIFAtVmFsdWUiLCANCiAgICAgICAgICAgICAgICAgICJQb29sIExlbmd0aCBQLVZhbHVlIiwgDQogICAgICAgICAgICAgICAgICAiTWVzc2FnZSIpLA0KICAgIGFsaWduID0gImMiLCAgIyBDZW50ZXItYWxpZ24gdGhlIGNvbHVtbnMNCiAgICByb3cubmFtZXMgPSBGQUxTRQ0KICApICMgbG9vayBvdXQgZm9yIHAgdmFsdWVzIDwwLjA1IHdoaWNoIGluZGljYXRlIG5vbi1ub3JtYWxpdHkNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIEZ1bmN0aW9uIHRvIHJ1biBMZXZlbmUncyBUZXN0IGZvciBlYWNoIHZhcmlhYmxlDQpydW5fbGV2ZW5lc190ZXN0IDwtIGZ1bmN0aW9uKHBvb2xfc3VtbWFyeV9kZikgew0KICAjIENyZWF0ZSBhIGxpc3Qgb2YgdmFyaWFibGVzIHRvIHRlc3QNCiAgdmFyaWFibGVzIDwtIGMoInNhZ2l0dGFsX2FyZWEiLCAibWF4X3Jlc2lkdWFsX2RlcHRoIiwgInBvb2xfbGVuZ3RoIikNCiAgDQogICMgSW5pdGlhbGl6ZSBhIGxpc3QgdG8gc3RvcmUgTGV2ZW5lJ3MgdGVzdCByZXN1bHRzDQogIGxldmVuZV9yZXN1bHRzX2xpc3QgPC0gbGlzdCgpDQogIA0KICAjIEl0ZXJhdGUgb3ZlciBlYWNoIHZhcmlhYmxlDQogIGZvciAodmFyIGluIHZhcmlhYmxlcykgew0KICAgIGxldmVuZV90ZXN0IDwtIGxldmVuZVRlc3QoYXMuZm9ybXVsYShwYXN0ZSh2YXIsICJ+IGludGVyYWN0aW9uKFNpdGUsIHllYXIpIiwgc2VwID0gIiIpKSwgZGF0YSA9IHBvb2xfc3VtbWFyeV9kZikNCiAgICANCiAgICAjIFN0b3JlIHRoZSByZXN1bHRzIGluIHRoZSBsaXN0DQogICAgbGV2ZW5lX3Jlc3VsdHNfbGlzdFtbdmFyXV0gPC0gbGV2ZW5lX3Rlc3QNCiAgfQ0KICANCiAgIyBSZXR1cm4gdGhlIGxpc3Qgb2YgTGV2ZW5lJ3MgdGVzdCByZXN1bHRzDQogIHJldHVybihsZXZlbmVfcmVzdWx0c19saXN0KQ0KfQ0KDQojIFJ1biBMZXZlbmUncyB0ZXN0DQpsZXZlbmVfcmVzdWx0cyA8LSBydW5fbGV2ZW5lc190ZXN0KHBvb2xfc3VtbWFyeV9maWx0ZXJlZCkNCg0KIyBEaXNwbGF5IExldmVuZSdzIHRlc3QgcmVzdWx0cyB3aXRoIHZhcmlhYmxlIG5hbWVzDQpmb3IgKHZhcl9uYW1lIGluIG5hbWVzKGxldmVuZV9yZXN1bHRzKSkgew0KICBjYXQoIlxuLS0tIExldmVuZSdzIFRlc3QgUmVzdWx0cyBmb3IiLCB2YXJfbmFtZSwgIi0tLVxuIikNCiAgcHJpbnQobGV2ZW5lX3Jlc3VsdHNbW3Zhcl9uYW1lXV0pDQp9ICMgSWYgcCA8IDAuMDUgdGhlbiB2YXJpYW5jZSAqaXMqIGRpZmZlcmVudCBhbW9uZyBncm91cHMgDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgRnVuY3Rpb24gdG8gY2FsY3VsYXRlIHNrZXduZXNzIGFuZCBrdXJ0b3Npcw0KY2FsY3VsYXRlX3NrZXdfa3VydCA8LSBmdW5jdGlvbihwb29sX3N1bW1hcnlfZGYpIHsNCiAgIyBDcmVhdGUgYSBsaXN0IG9mIHZhcmlhYmxlcyB0byBhbmFseXplDQogIHZhcmlhYmxlcyA8LSBjKCJzYWdpdHRhbF9hcmVhIiwgIm1heF9yZXNpZHVhbF9kZXB0aCIsICJwb29sX2xlbmd0aCIpDQogIA0KICAjIEluaXRpYWxpemUgYSBsaXN0IHRvIHN0b3JlIHRoZSByZXN1bHRzDQogIHNrZXdfa3VydF9saXN0IDwtIGxpc3QoKQ0KICANCiAgIyBJdGVyYXRlIG92ZXIgZWFjaCB2YXJpYWJsZQ0KICBmb3IgKHZhciBpbiB2YXJpYWJsZXMpIHsNCiAgICBza2V3IDwtIHNrZXduZXNzKHBvb2xfc3VtbWFyeV9kZltbdmFyXV0sIG5hLnJtID0gVFJVRSkNCiAgICBrdXJ0IDwtIGt1cnRvc2lzKHBvb2xfc3VtbWFyeV9kZltbdmFyXV0sIG5hLnJtID0gVFJVRSkNCiAgICANCiAgICAjIFN0b3JlIHRoZSByZXN1bHRzDQogICAgc2tld19rdXJ0X2xpc3RbW3Zhcl1dIDwtIGRhdGEuZnJhbWUoDQogICAgICBWYXJpYWJsZSA9IHZhciwNCiAgICAgIFNrZXduZXNzID0gc2tldywNCiAgICAgIEt1cnRvc2lzID0ga3VydA0KICAgICkNCiAgfQ0KICANCiAgIyBDb21iaW5lIHRoZSByZXN1bHRzIGludG8gYSBzaW5nbGUgZGF0YWZyYW1lDQogIHNrZXdfa3VydF9kZiA8LSBkby5jYWxsKHJiaW5kLCBza2V3X2t1cnRfbGlzdCkNCiAgDQogIHJldHVybihza2V3X2t1cnRfZGYpDQp9DQoNCiMgQ2FsY3VsYXRlIHNrZXduZXNzIGFuZCBrdXJ0b3Npcw0Kc2tld19rdXJ0X3Jlc3VsdCA8LSBjYWxjdWxhdGVfc2tld19rdXJ0KHBvb2xfc3VtbWFyeV9maWx0ZXJlZCkNCg0KIyBEaXNwbGF5IHNrZXduZXNzIGFuZCBrdXJ0b3NpcyByZXN1bHRzDQpwcmludChza2V3X2t1cnRfcmVzdWx0KQ0KYGBgDQoNCklmLCBiYXNlZCBvbiB0aGUgYWJvdmUgZXZhbHVhdGlvbiwgeW91ciBkYXRhIGFwcGVhciB0byBiZSB1bnN1aXRhYmxlIGZvciB0aGUgaW50ZW5kZWQgaW5mZXJlbnRpYWwgdGVzdCB5b3UgbWF5IHdpc2ggdG8gdXNlIGFuIGFsdGVybmF0aXZlIG5vbi1wYXJhbWV0cmljIHRlc3Qgb3IgdHJhbnNmb3JtIHRoZSBkYXRhLiBXZSBwcm92aWRlIHNvbWUgYXNzaXN0YW5jZSBmb3IgdHJhbnNmb3JtYXRpb25zIGhlcmUsIGJ1dCB0aGlzIHBhcnQgbWF5IHJlcXVpcmUgc29tZSBtb3JlIHdvcmsgb24geW91ciBwYXJ0IHNpbmNlIHdlIGNhbm5vdCBwcmVkaWN0IHdoYXQgeW91ciBkYXRhIHdpbGwgbmVlZC4NCg0KQXMgYW4gZXhhbXBsZSwgb3VyIGRhdGEgYXBwZWFyZWQgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgKHA+MC4wNSBTaGFwaXJvLVdpbGspIGJ1dCBMZXZlbmUncyB0ZXN0IHJldmVhbGVkIHRoYXQgc2FnaXR0YWwgYXJlYSB2YXJpYW5jZSB3YXMgdW5lcXVhbCBhY3Jvc3Mgc2l0ZS15ZWFycyAocDwwLjA1KS4gV2UgdGhlcmVmb3JlIGxvZy10cmFuc2Zvcm1lZCB0aGUgc2FnaXR0YWwgYXJlYSBkYXRhIGFuZCByZS1yYW4gdGhlIGFib3ZlIGRpYWdub3N0aWNzLCB3aXRoIExldmVuZSdzIHRlc3QgcmV0dXJuZWQgYXMgbm9uLXNpZ25pZmljYW50IGFuZCB0aGVyZWZvcmUgYWNjZXB0YWJsZSB0byBiZSB1c2VkIGluIEFOT1ZBcy4gTm90ZSB0aGF0IG9ubHkgdGhvc2UgbWV0cmljcyB0aGF0IGRvIG5vdCBtZWV0IHRoZSBhc3N1bXB0aW9ucyBuZWVkIHRvIGJlIHRyYW5zZm9ybWVkLg0KDQpUaGUgY29kZSB3ZSB1c2VkIGZvciB0aGUgdHJhbnNmb3JtYXRpb24gaXMgYmVsb3cuIElmIHlvdSBuZWVkIHRvIHRyYW5zZm9ybSB0aGUgZGF0YSwgZm9sbG93IHRoZXNlIHN0ZXBzOg0KDQojIyMgVHJhbnNmb3JtYXRpb25zDQoNCjEuIEFkZCB5b3VyIHRyYW5zZm9ybWF0aW9uKHMpIHRvIHRoZSBjb2RlIGNodW5rIGJlbG93LiBZb3UgbXVzdCBhZGQgYSBmb3JtdWxhIHRvIGNhbGN1bGF0ZSBhbiBhcHByb3ByaWF0ZSB0cmFuc2Zvcm1hdGlvbiBmb3IgZWFjaCBhcHBsaWNhYmxlIHZhcmlhYmxlIHdpdGhpbiAqdHJhbnNmb3JtYXRpb25zIDwtIGxpc3QoLi4uKSopLiBBcyBhbiBleGFtcGxlLCBpZiB5b3Ugd2FudCB0byB0cnkgYSBsb2cgdHJhbnNmb3JtYXRpb24sIHJlcGxhY2UgJ2lkZW50aXR5LCcgaW4gdGhlIGJlbG93IGNvZGUgd2l0aCAnZnVuY3Rpb24oeCkgaWZlbHNlKHggPiAwLCBsb2coeCksIE5BKSwnDQoNCjIuIFJlLXJ1biB0aGUgYWJvdmUgZGlhZ25vc3RpY3MgY29kZSBhZnRlciB1cGRhdGluZyB0aGUgYXBwbGljYWJsZSB2YXJpYWJsZSBuYW1lKHMpIGZvciBlYWNoIGRpYWdub3N0aWMgdGVzdDogd2hlcmUgaXQgc2F5cyAnKnZhcmlhYmxlcyA8LSBjKCJzYWdpdHRhbF9hcmVhIiwgIm1heF9yZXNpZHVhbF9kZXB0aCIsICJwb29sX2xlbmd0aCIpKicgeW91IHdpbGwgdXBkYXRlIGVhY2ggYXBwbGljYWJsZSB0cmFuc2Zvcm1lZCB2YXJpYWJsZSBuYW1lKHMpIHRvICIqdHJhbnNmb3JtZWRfKnZhcmlhYmxlX25hbWUiDQoNCjMuIE9uY2UgeW91IGhhdmUgYSB0cmFuc2Zvcm1lZCB2YXJpYWJsZSB0aGF0IG1lZXRzIHRoZSBhc3N1bXB0aW9ucyBvZiB0aGUgQU5PVkEsIHVwZGF0ZSB0aGUgQU5PVkEgaW5mZXJlbnRpYWwgdGVzdCBjb2RlIChpbiB0aGUgc3Vic2VxdWVudCBjb2RlIGNodW5rKSB0byB1c2UgdGhlICIqdHJhbnNmb3JtZWRfKnZhcmlhYmxlX25hbWUiDQoNCmBgYHtyIHRyYW5zZm9ybWF0aW9uc30NCiMgRnVuY3Rpb24gdG8gYXBwbHkgdHJhbnNmb3JtYXRpb25zIGFuZCBhcHBlbmQgdG8gdGhlIGRhdGFmcmFtZQ0KYXBwbHlfdHJhbnNmb3JtYXRpb25zIDwtIGZ1bmN0aW9uKGRhdGEsIHRyYW5zZm9ybWF0aW9ucykgew0KICBmb3IgKHZhciBpbiBuYW1lcyh0cmFuc2Zvcm1hdGlvbnMpKSB7DQogICAgdHJhbnNmb3JtX2ZuIDwtIHRyYW5zZm9ybWF0aW9uc1tbdmFyXV0NCiAgICB0cmFuc2Zvcm1lZF92YXIgPC0gcGFzdGUwKCJ0cmFuc2Zvcm1lZF8iLCB2YXIpDQogICAgIyBBcHBseSB0aGUgdHJhbnNmb3JtYXRpb24gYW5kIGFwcGVuZCBhcyBhIG5ldyBjb2x1bW4NCiAgICBkYXRhW1t0cmFuc2Zvcm1lZF92YXJdXSA8LSB0cmFuc2Zvcm1fZm4oZGF0YVtbdmFyXV0pDQogIH0NCiAgcmV0dXJuKGRhdGEpDQp9DQoNCiMgRGVmaW5lIHRyYW5zZm9ybWF0aW9ucyBhcyBhIG5hbWVkIGxpc3QuIFlvdSBjYW4gYWRkIGFwcHJvcHJpYXRlIHRyYW5zZm9ybWF0aW9ucyBoZXJlLCB0aGVuIG9uY2UgeW91IGNvbmZpcm0gdGhlIHRyYW5zZm9ybWF0aW9uIGlzIHN1aXRhYmxlLCBhbWVuZCB0aGUgYW5vdmEgY29kZSB0byBjYWxsIHRoZSBjb3JyZWN0IHZhcmlhYmxlDQoNCiMgVXNlICdpZGVudGl0eScgaWYgbm8gdHJhbnNmb3JtYXRpb24gaXMgbmVlZGVkDQp0cmFuc2Zvcm1hdGlvbnMgPC0gbGlzdCgNCiAgc2FnaXR0YWxfYXJlYSA9IGlkZW50aXR5LCAjIGV4YW1wbGUgY29kZSBmbyBsb2ctdHJhbnNmb3JtYXRpb246IHJlcGxhY2UgJ2lkZW50aXR5LCcgd2l0aCAnZnVuY3Rpb24oeCkgaWZlbHNlKHggPiAwLCBsb2coeCksIE5BKSwnIA0KICBtYXhfcmVzaWR1YWxfZGVwdGggPSBpZGVudGl0eSwgICMgTm8gdHJhbnNmb3JtYXRpb24NCiAgcG9vbF9sZW5ndGggPSBpZGVudGl0eSAjIG5vIHRyYW5zZm9ybWF0aW9uIA0KKQ0KDQojIEFwcGx5IHRyYW5zZm9ybWF0aW9ucyBhbmQgdXBkYXRlIHRoZSBkYXRhZnJhbWUNCnBvb2xfc3VtbWFyeV9maWx0ZXJlZCA8LSBhcHBseV90cmFuc2Zvcm1hdGlvbnMocG9vbF9zdW1tYXJ5X2ZpbHRlcmVkLCB0cmFuc2Zvcm1hdGlvbnMpDQpgYGANCiANCiMjIyBBTk9WQSANCg0KT25jZSB5b3UgaGF2ZSBzYXRpc2ZpZWQgeW91cnNlbGYgdGhhdCB5b3VyIGRhdGEgKG9yIHRyYW5zZm9ybWVkIGRhdGEpIGFyZSBzdWl0YWJsZSwgd2Ugd2lsbCBydW4gdGhlIGluZmVyZW50aWFsIHRlc3RzLiBXZSB1c2UgQU5PVkEgdG8gYXNrIHdoZXRoZXIgdGhlIGZvbGxvd2luZyBtZXRyaWNzIGRpZmZlciBhbW9uZyBzaXRlcywgeWVhcnMsIGFuZCBzaXRlKnllYXIgaW50ZXJhY3Rpb25zOg0KDQotIFNhZ2l0dGFsIGFyZWENCi0gTWF4aW11bSByZXNpZHVhbCBkZXB0aA0KLSBQb29sIGxlbmd0aA0KDQpJZiB5b3UgZGlkIHVzZSB0cmFuc2Zvcm1lZCBkYXRhLCBlbnN1cmUgeW91IHJlZmVyZW5jZSB0aGF0IHZhcmlhYmxlIGluIHRoZSBiZWxvdyBjb2RlIChlLmcuLCBjaGFuZ2UgInNhZ2l0dGFsX2FyZWEiIHRvICJ0cmFuc2Zvcm1lZF9zYWdpdHRhbF9hcmVhIikNCg0KYGBge3IgcG9vbCBBTk9WQXN9DQojIEZ1bmN0aW9uIHRvIHJ1biBBTk9WQSBmb3IgYSBnaXZlbiB2YXJpYWJsZQ0KcnVuX2Fub3ZhIDwtIGZ1bmN0aW9uKGRhdGEsIHZhcmlhYmxlKSB7DQogIGZvcm11bGEgPC0gYXMuZm9ybXVsYShwYXN0ZSh2YXJpYWJsZSwgIn4gU2l0ZSAqIFRpbWVfQ2F0ZWdvcnkiKSkNCiAgYW5vdmFfcmVzdWx0IDwtIGFvdihmb3JtdWxhLCBkYXRhID0gZGF0YSkNCiAgc3VtbWFyeShhbm92YV9yZXN1bHQpDQp9DQoNCiMgRW5zdXJlIHRyYW5zZm9ybWVkIGRhdGEgaXMgdXNlZCBpbiB0aGUgQU5PVkEgaWYgbmVjZXNzYXJ5IChjaGFuZ2UgdGhlIHZhcmlhYmxlIG5hbWUgaW4gcXVvdGF0aW9uIG1hcmtzIGluIHRoZXNlIG5leHQgcm93cykNCmFub3ZhX21heF9yZXNpZHVhbF9kZXB0aCA8LSBydW5fYW5vdmEocG9vbF9zdW1tYXJ5X2ZpbHRlcmVkLCAibWF4X3Jlc2lkdWFsX2RlcHRoIikNCmFub3ZhX3Bvb2xfbGVuZ3RoIDwtIHJ1bl9hbm92YShwb29sX3N1bW1hcnlfZmlsdGVyZWQsICJwb29sX2xlbmd0aCIpDQphbm92YV9zYWdpdHRhbF9hcmVhIDwtIHJ1bl9hbm92YShwb29sX3N1bW1hcnlfZmlsdGVyZWQsICJzYWdpdHRhbF9hcmVhIikNCmBgYA0KDQpgYGB7ciB2aWV3IHBvb2wgQU5PVkFzLCBlY2hvID0gRkFMU0V9DQojIHZpZXcgcmVzdWx0cw0KcHJpbnQoIl9fX19fX19fX19fX19fX0FOT1ZBIGZvciBNYXggUmVzaWR1YWwgRGVwdGhfX19fX19fX19fX19fXyIpDQpwcmludChhbm92YV9tYXhfcmVzaWR1YWxfZGVwdGgpDQpwcmludCgiX19fX19fX19fX19fX19fQU5PVkEgZm9yIFJlc2lkdWFsIFBvb2wgTGVuZ3RoX19fX19fX19fX19fX18iKQ0KcHJpbnQoYW5vdmFfcG9vbF9sZW5ndGgpDQpwcmludCgiX19fX19fX19fX19fX19fQU5PVkEgZm9yIFJlc2lkdWFsIFBvb2wgU2FnaXR0YWwgQXJlYV9fX19fX19fX19fX19fIikNCnByaW50KGFub3ZhX3NhZ2l0dGFsX2FyZWEpDQoNCiMgZXhwb3J0IHRlc3Qgc3VtbWFyaWVzDQptYXhkZWVwX291dHB1dCA8LSBjYXB0dXJlLm91dHB1dChwcmludChhbm92YV9tYXhfcmVzaWR1YWxfZGVwdGgpKSAgIyBDYXB0dXJlIHRoZSBwcmludGVkIG91dHB1dHMNCnBvb2xsb25nX291dHB1dCA8LSBjYXB0dXJlLm91dHB1dChwcmludChhbm92YV9wb29sX2xlbmd0aCkpICAjIA0Kc2FnZ2lfb3V0cHV0IDwtIGNhcHR1cmUub3V0cHV0KHByaW50KGFub3ZhX3NhZ2l0dGFsX2FyZWEpKSAgIyANCnN1bW1hcnlfdGV4dCA8LSBjKCJBTk9WQSBmb3IgTWF4IFJlc2lkdWFsIERlcHRoOiIsIG1heGRlZXBfb3V0cHV0LCAiXG5cblxuIiwgIkFOT1ZBIGZvciBSZXNpZHVhbCBQb29sIExlbmd0aDoiLCBwb29sbG9uZ19vdXRwdXQsIlxuXG5cbiIsICAiQU5PVkEgZm9yIFJlc2lkdWFsIFBvb2wgU2FnaXR0YWwgQXJlYToiLCBzYWdnaV9vdXRwdXQpDQpleHBvcnRfc3VtbWFyeShzdW1tYXJ5X3RleHQsICJSZXNpZHVhbCBQb29sIEFOT1ZBcyIpDQpgYGANCg0KVGFrZSBzb21lIHRpbWUgdG8gZW5zdXJlIHlvdSB1bmRlcnN0YW5kIHdoYXQgdGhlIGFib3ZlIHRlbGxzIHlvdSwgcGFydGljdWxhcmx5IHdpdGggcmVnYXJkcyB0byB5b3VyIGNob3NlbiBtZXRyaWMgb2Ygc3VjY2Vzcy4gSW4gdGhlIGV4YW1wbGUgQU5PVkEgYWJvdmUsIHRoZXJlIHdhcyBvbmUgc2l0ZTp0aW1lIGludGVyYWN0aW9uIHRoYXQgd2FzIHNpZ25pZmljYW50IGF0IHA9MC4wNSAobWF4aW11bSByZXNpZHVhbCBkZXB0aCksIGFuZCB0aGUgdGltZSBjYXRlZ29yeSB3YXMgc2lnbmlmaWNhbnQgZm9yIGFsbCBtZXRyaWNzLiBUaGlzIHN1Z2dlc3RzIHRoYXQgYSBjaGFuZ2UgaW4gbWV0cmljcyBvdmVyIHRpbWUgd2FzIG5vdCBsaWtlbHkgZHVlIHRvIGNoYW5jZSwgYnV0IG9ubHkgZm9yIG1heGltdW0gcmVzaWR1YWwgZGVwdGggZGlkIG91ciByZXN0b3JhdGlvbiBzaXRlIGNoYW5nZSBvdmVyIHRpbWUgZGlmZmVyZW50bHkgdGhhbiB0aGUgY29udHJvbCBzaXRlLiBIb3dldmVyLCB3ZSBjaG9zZSBzYWdpdHRhbCBhcmVhIGFzIG91ciAqYSBwcmlvcmkqIHN1Y2Nlc3MgbWV0cmljLCBzbyB3ZSBjYW5ub3QgaW50ZXJwcmV0IHRoaXMgYXMgYSBzdWNjZXNzZnVsIHJlc3RvcmF0aW9uIGFjdGlvbiBhdCB0aGlzIHBvaW50IGluIHRpbWUuDQoNCkFsdGhvdWdoIHdlIGNvdWxkIG5vdCBkaXNjYXJkIG91ciBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzICh0aGF0IGNoYW5nZXMgYXQgb3VyIHJlc3RvcmF0aW9uIHNpdGUgd2VyZSBub3QgZHVlIHRvIG91ciBhY3Rpb25zKSwgd2UgbWF5IHN0aWxsIGxlYXJuIGZyb20gdGhlIGFib3ZlIHRvIGluZm9ybSBmdXR1cmUgcGxhbnMuIENvbnNpZGVyIGFsbCB0aGUgaW5mb3JtYXRpb24gd2UgaGF2ZSBnZW5lcmF0ZWQgc28gZmFyIGZvciB5b3UgZGF0YSwgYW5kIHRha2Ugc29tZSB0aW1lIHRvIHRoaW5rIGFib3V0IGl0LiBTdGVwIG91dHNpZGUgdG8gZG8gdGhpcyBpZiB5b3UgYXJlIGFibGUgdG8uIENvbnNpZGVyIHdoYXQgaXQgbWlnaHQgbWVhbiBpZiBwb29scyBhdCBvdXIgcmVzdG9yYXRpb24gc2l0ZSBhcHBlYXIgZGVlcGVyIG9uIGF2ZXJhZ2UsIGJ1dCBzYWdpdHRhbCBhcmVhcyBkaWQgbm90IGNoYW5nZT8gQ29uc2lkZXIgd2hldGhlciB0aGVyZSBhcmUgcG9vbHMgdGhhdCBkaWQgb3IgZGlkIG5vdCBzY3JhcGUgdGhyb3VnaCB0aGUgc3Vic2V0dGluZyBjdXQtb2ZmIChpLmUuLCB2ZXJ5IHNtYWxsIHBvb2xzIG9mIG1hcmdpbmFsIHZhbHVlKSwgaG93IG1pZ2h0IHRoZXkgaW1wYWN0IHlvdXIgbWVhbiB2YWx1ZXM/IFdhcyB0aGVyZSBhIGJpZyBlbm91Z2ggY2hhbmdlIGluIHRoZXNlIG1hcmdpbmFsIGNhc2VzIHRvIGNyZWF0ZSBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2U/IElzIGFueSBvZiB0aGlzIGJpb2xvZ2ljYWxseSBvciBnZW9tb3JwaGljYWxseSBtZWFuaW5nZnVsIGJhc2VkIG9uIHlvdXIgaHlwb3RoZXNlcz8NCg0KVGhpcyBpcyBhbGwgZW5kbGVzc2x5IGludGVyZXN0aW5nL21hZGRlbmluZyAoZGVwZW5kaW5nIG9uIHlvdXIgcGVyc3BlY3RpdmUpIGFuZCB3ZSBoaWdobHkgcmVjb21tZW5kIGZpbmRpbmcgYW5vdGhlciBwZXJzb24gKG9yIHNldmVyYWwpIHRvIHRhbGsgaXQgdGhyb3VnaCB3aXRoLiBCZWZvcmUgbW92aW5nIG9uIHRvIGZ1cnRoZXIgYW5hbHlzZXMsIGVuc3VyZSB5b3UgaGF2ZSBhIHJlYXNvbmFibGUgdW5kZXJzdGFuZGluZyBvZiB0aGUgaW5mb3JtYXRpb24gc28gZmFyLiBUYWtlIGEgc3RlcCBiYWNrIHRvIHRoaW5rIGFib3V0IHRoZSBiaWcgcGljdHVyZS4NCg0KIyBWb2x1bWUgRXN0aW1hdGlvbg0KDQpJZiB5b3UgaGF2ZSBubyBoeXBvdGhlc2VzIG9yIHByZWRpY3Rpb25zIHNwZWNpZmljYWxseSByZWdhcmRpbmcgcG9vbCAqdm9sdW1lcyosIHlvdSBtYXkgd2lzaCB0byBza2lwIHRoaXMgc2VjdGlvbiBhbmQgbW92ZSBvbnRvICpGaW5lIFNlZGltZW50IGluIFBvb2xzKi4NCg0KSWYgeW91IHRvb2sgd2V0dGVkIHdpZHRoIG1lYXN1cmVtZW50cyBhdCB0cmFuc2VjdHMgYWxvbmcgdGhlIHJlYWNoLCB5b3UgY2FuIHVzZSB0aGUgYXZlcmFnZSB0byBlc3RpbWF0ZSB0aGUgdm9sdW1lIG9mIHJlc2lkdWFsIHBvb2xzLiBUaGlzIGFwcHJvYWNoIGlzIGEgbW9yZSBzaW1wbGlmaWVkIGFwcHJvYWNoIHRoYW4gdGhhdCBvZiBSb2Jpc29uICgxOTk4KSB3aG8gbGlua2VkIHdldHRlZCB3aWR0aCBtZWFzdXJlbWVudHMgdG8gbmVhcmJ5IGxvbmdpdHVkaW5hbCBpbnRlcnZhbHMuIElmIHRoaXMgaXMgcG9zc2libGUgZm9yIHRoZSBkYXRhIHlvdSBjb2xsZWN0ZWQsIHdlIHJlY29tbWVuZCByZXZpZXdpbmcgUm9iaXNvbiAoMTk5OCkgdG8gb2J0YWluIG1vcmUgJ2xvY2FsaXNlZCcgZXN0aW1hdGVzIG9mIHdldHRlZCB3aWR0aC4gSG93ZXZlciwgYmVhciBpbiBtaW5kIHRoYXQgdGhlcmUgbWF5IHJlZ2FyZGxlc3MgYmUgYSBiaWFzIGluIHJlc2lkdWFsIHdldHRlZCB3aWR0aHMgaWYgKGUuZy4pIHBvb2xzIHRlbmQgdG8gYmUgd2lkZXIgdGhhbiByaWZmbGVzLiBGb3Igb3VyIHNpbXBsaWZpZWQgYXBwcm9hY2ggd2UgYXNzdW1lIHRoYXQgdGhlIHdldHRlZCB3aWR0aCBpcyBjb25zdGFudCBmb3IgdGhlIHJlYWNoLCBhbmQgd2UgYWxzbyBhc3N1bWUgdGhhdCB0aGUgc3RyZWFtIGNyb3NzIHNlY3Rpb25zIGFyZSBwZXJmZWN0IHRyaWFuZ2xlcy4gV2UgdGhlbiB1c2UgdGhlIHJhdGlvIG9mIHJlc2lkdWFsIGRlcHRocyB0byBmaWVsZC1yZWNvcmRlZCBkZXB0aHMgdG8gZXN0aW1hdGUgdGhlIHJlc2lkdWFsIHdldHRlZCB3aWR0aHMgb2YgcG9vbHMgd2hlbiBmbG93IGFwcHJvYWNoZXMgemVyby4gDQoNCkNvbnNpZGVyaW5nIGNoYW5nZXMgaW4gKGNvYXJzZWx5LWVzdGltYXRlZCkgcG9vbCB2b2x1bWUgY2FuIGJlIG9mIGludGVyZXN0IGR1ZSB0byB0aGUgcG90ZW50aWFsIGZvciBuYXR1cmFsIHByb2Nlc3NlcyB0byBhbHRlciBib3RoIHRoZSBsb25naXR1ZGluYWwgYW5kIGNyb3NzLXNlY3Rpb25hbCBoZXRlcm9nZW5laXR5IG9mIGEgc3RyZWFtLiBGb3IgZXhhbXBsZSwgcGVyaGFwcyB3ZSBhcmUgYW50aWNpcGF0aW5nIGEgbmFycm93ZXIgd2V0dGVkIGNoYW5uZWwgd2l0aCBkZWVwZXIgcG9vbHMsIGFuZCB3YW50IHRvIGV4cGxvcmUgd2hhdCB0aGlzIG1lYW5zIGZvciBwb29sIHZvbHVtZS4gSG93ZXZlciwgYXMgc3VnZ2VzdGVkIGJ5IHRoZSBjb2Fyc2UgYXNzdW1wdGlvbnMgd2UgbWFkZSBmb3IgdGhpcyBjYWxjdWxhdGlvbiwgaW50ZXJwcmV0IHJlc3VsdHMgd2l0aCBjYXV0aW9uLiANCg0KYGBge3IgcG9vbCB2b2x1bWVzLCBlY2hvID0gRkFMU0V9DQpjYWxjdWxhdGVfcG9vbF92b2x1bWVzX2Zvcl9zaXRlc195ZWFycyA8LSBmdW5jdGlvbihkZiwgcG9vbF9zdW1tYXJ5X2RmKSB7DQogICMgSW5pdGlhbGl6ZSBhIGxpc3QgdG8gc3RvcmUgcmVzdWx0cyBmb3IgZWFjaCBzaXRlLXllYXIgY29tYmluYXRpb24NCiAgcG9vbF92b2x1bWVzX2xpc3QgPC0gbGlzdCgpDQogIA0KICAjIEdyb3VwIHRoZSBkYXRhIGJ5IFNpdGUgYW5kIFllYXINCiAgZ3JvdXBlZF9wb29sX3N1bW1hcnkgPC0gc3BsaXQocG9vbF9zdW1tYXJ5X2RmLCBsaXN0KHBvb2xfc3VtbWFyeV9kZiRTaXRlLCBwb29sX3N1bW1hcnlfZGYkeWVhcikpDQogIA0KICAjIEl0ZXJhdGUgb3ZlciBlYWNoIFNpdGUtWWVhciBncm91cA0KICBmb3IgKGdyb3VwX25hbWUgaW4gbmFtZXMoZ3JvdXBlZF9wb29sX3N1bW1hcnkpKSB7DQogICAgIyBHZXQgdGhlIGN1cnJlbnQgZ3JvdXANCiAgICBncm91cCA8LSBncm91cGVkX3Bvb2xfc3VtbWFyeVtbZ3JvdXBfbmFtZV1dDQogICAgDQogICAgIyBFeHRyYWN0IHRoZSBzaXRlIGFuZCB5ZWFyDQogICAgc2l0ZSA8LSB1bmlxdWUoZ3JvdXAkU2l0ZSkNCiAgICB5ZWFyIDwtIHVuaXF1ZShncm91cCR5ZWFyKQ0KICAgIA0KICAgICMgQ2hlY2sgaWYgc2l0ZSBvciB5ZWFyIGFyZSBpbnZhbGlkDQogICAgaWYgKGxlbmd0aChzaXRlKSAhPSAxIHx8IGxlbmd0aCh5ZWFyKSAhPSAxIHx8IGlzLm5hKHNpdGUpIHx8IGlzLm5hKHllYXIpKSB7DQogICAgICB3YXJuaW5nKHNwcmludGYoIkludmFsaWQgU2l0ZSBvciBZZWFyIGluIGdyb3VwOiAlcy4gU2tpcHBpbmcuLi4iLCBncm91cF9uYW1lKSkNCiAgICAgIG5leHQNCiAgICB9DQogICAgDQogICAgIyBGaWx0ZXIgdGhlIG1haW4gZGF0YWZyYW1lIHRvIG1hdGNoIHRoZSBjdXJyZW50IFNpdGUtWWVhcg0KICAgIHNpdGVfeWVhcl9kYXRhIDwtIGRmW2RmJFNpdGUgPT0gc2l0ZSAmIGRmJHllYXIgPT0geWVhciwgXQ0KICAgIA0KICAgICMgQ2hlY2sgaWYgdGhlIHN1YnNldCBpcyBlbXB0eQ0KICAgIGlmIChucm93KHNpdGVfeWVhcl9kYXRhKSA9PSAwKSB7DQogICAgICB3YXJuaW5nKHNwcmludGYoIk5vIGRhdGEgZm91bmQgZm9yIFNpdGUgJyVzJyBhbmQgWWVhciAnJXMnLiBTa2lwcGluZy4uLiIsIHNpdGUsIHllYXIpKQ0KICAgICAgbmV4dA0KICAgIH0NCiAgICANCiAgICAjIEdldCB0aGUgc3Vic2V0IG9mIHBvb2wgSURzIGZvciB0aGlzIGdyb3VwDQogICAgc3Vic2V0X3Bvb2xfaWRzIDwtIGFzLm51bWVyaWMoZ3JvdXAkcG9vbF9pZCkgICMgQ29udmVydCB0byBudW1lcmljIGlmIG5lY2Vzc2FyeQ0KICAgIA0KICAgICMgRW5zdXJlIHRoZSBkYXRhZnJhbWUgaXMgc29ydGVkIGJ5IGRpc3RhbmNlDQogICAgc2l0ZV95ZWFyX2RhdGEgPC0gc2l0ZV95ZWFyX2RhdGFbb3JkZXIoc2l0ZV95ZWFyX2RhdGEkZGlzdGFuY2UpLCBdDQogICAgDQogICAgIyBGaWx0ZXIgdGhlIGRhdGFmcmFtZSB0byBvbmx5IGluY2x1ZGUgcm93cyBiZWxvbmdpbmcgdG8gdGhlIHN1YnNldCBvZiBwb29sIElEcw0KICAgIHNpdGVfeWVhcl9kYXRhIDwtIHNpdGVfeWVhcl9kYXRhW3NpdGVfeWVhcl9kYXRhJHBvb2xfaWQgJWluJSBzdWJzZXRfcG9vbF9pZHMsIF0NCiAgICANCiAgICAjIEluaXRpYWxpemUgYSBsaXN0IHRvIHN0b3JlIHZvbHVtZXMgZm9yIGVhY2ggcG9vbCBpbiB0aGlzIFNpdGUtWWVhciBncm91cA0KICAgIHBvb2xfdm9sdW1lcyA8LSBsaXN0KCkNCiAgICANCiAgICAjIEl0ZXJhdGUgb3ZlciB1bmlxdWUgcG9vbCBJRHMgaW4gdGhlIHN1YnNldA0KICAgIGZvciAocG9vbF9pZCBpbiBzdWJzZXRfcG9vbF9pZHMpIHsNCiAgICAgICMgU3Vic2V0IHRoZSBkYXRhIGZvciB0aGUgY3VycmVudCBwb29sDQogICAgICBwb29sX2RhdGEgPC0gc2l0ZV95ZWFyX2RhdGFbc2l0ZV95ZWFyX2RhdGEkcG9vbF9pZCA9PSBwb29sX2lkLCBdDQogICAgICANCiAgICAgICMgU2tpcCBpZiB0aGVyZSBhcmUgZmV3ZXIgdGhhbiAyIHBvaW50cyBpbiB0aGUgJ3Bvb2wnIChpbmNsdWRpbmcgb3V0bGV0LCBpLmUuIG5vdCBwb29scykNCiAgICAgIGlmIChucm93KHBvb2xfZGF0YSkgPCAyKSB7DQogICAgICAgIHBvb2xfdm9sdW1lc1tbYXMuY2hhcmFjdGVyKHBvb2xfaWQpXV0gPC0gTkENCiAgICAgICAgbmV4dA0KICAgICAgfQ0KICAgICAgDQogICAgICAjIEluaXRpYWxpemUgdGhlIHBvb2wgdm9sdW1lDQogICAgICBwb29sX3ZvbHVtZSA8LSAwDQogICAgICANCiAgICAgICMgTG9vcCB0aHJvdWdoIGNvbnNlY3V0aXZlIHJvd3MgdG8gY2FsY3VsYXRlIHNlZ21lbnQgdm9sdW1lcw0KICAgICAgZm9yIChpIGluIDE6KG5yb3cocG9vbF9kYXRhKSAtIDEpKSB7DQogICAgICAgICMgUmVzaWR1YWwgd2lkdGggYW5kIGRlcHRoIGZvciBjdXJyZW50IGFuZCBuZXh0IHBvaW50DQogICAgICAgIHdpZHRoX2kgPC0gcG9vbF9kYXRhJHJlc2lkdWFsX3dpZHRoW2ldDQogICAgICAgIGRlcHRoX2kgPC0gcG9vbF9kYXRhJHJlc2lkdWFsX2RlcHRoW2ldDQogICAgICAgIHdpZHRoX25leHQgPC0gcG9vbF9kYXRhJHJlc2lkdWFsX3dpZHRoW2kgKyAxXQ0KICAgICAgICBkZXB0aF9uZXh0IDwtIHBvb2xfZGF0YSRyZXNpZHVhbF9kZXB0aFtpICsgMV0NCiAgICAgICAgDQogICAgICAgICMgQ2hlY2sgZm9yIE5BIHZhbHVlcw0KICAgICAgICBpZiAoaXMubmEod2lkdGhfaSkgfHwgaXMubmEoZGVwdGhfaSkgfHwgaXMubmEod2lkdGhfbmV4dCkgfHwgaXMubmEoZGVwdGhfbmV4dCkpIHsNCiAgICAgICAgICBuZXh0DQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgICMgQ2FsY3VsYXRlIGNyb3NzLXNlY3Rpb25hbCBhcmVhcw0KICAgICAgICBhcmVhX2kgPC0gMC41ICogd2lkdGhfaSAqIGRlcHRoX2kNCiAgICAgICAgYXJlYV9uZXh0IDwtIDAuNSAqIHdpZHRoX25leHQgKiBkZXB0aF9uZXh0DQogICAgICAgIA0KICAgICAgICAjIENhbGN1bGF0ZSBtZWFuIGNyb3NzLXNlY3Rpb25hbCBhcmVhDQogICAgICAgIG1lYW5fYXJlYSA8LSAoYXJlYV9pICsgYXJlYV9uZXh0KSAvIDINCiAgICAgICAgDQogICAgICAgICMgQ2FsY3VsYXRlIGRpc3RhbmNlIGJldHdlZW4gY3VycmVudCBhbmQgbmV4dCBwb2ludA0KICAgICAgICBzcGFjaW5nIDwtIHBvb2xfZGF0YSRkaXN0YW5jZVtpICsgMV0gLSBwb29sX2RhdGEkZGlzdGFuY2VbaV0NCiAgICAgICAgDQogICAgICAgICMgQWRkIHNlZ21lbnQgdm9sdW1lIHRvIHRvdGFsIHBvb2wgdm9sdW1lDQogICAgICAgIHBvb2xfdm9sdW1lIDwtIHBvb2xfdm9sdW1lICsgbWVhbl9hcmVhICogc3BhY2luZw0KICAgICAgfQ0KICAgICAgDQogICAgICAjIFN0b3JlIHRoZSB2b2x1bWUgZm9yIHRoaXMgcG9vbA0KICAgICAgcG9vbF92b2x1bWVzW1thcy5jaGFyYWN0ZXIocG9vbF9pZCldXSA8LSBwb29sX3ZvbHVtZQ0KICAgIH0NCiAgICANCiAgICAjIENvbnZlcnQgdGhlIHJlc3VsdHMgaW50byBhIGRhdGFmcmFtZSBmb3IgdGhlIGN1cnJlbnQgU2l0ZS1ZZWFyIGdyb3VwDQogICAgcG9vbF92b2x1bWVzX2RmIDwtIGRhdGEuZnJhbWUoDQogICAgICBwb29sX2lkID0gbmFtZXMocG9vbF92b2x1bWVzKSwNCiAgICAgIHBvb2xfdm9sdW1lX20zID0gdW5saXN0KHBvb2xfdm9sdW1lcyksDQogICAgICBTaXRlID0gc2l0ZSwNCiAgICAgIHllYXIgPSB5ZWFyDQogICAgKQ0KICAgIA0KICAgICMgQXBwZW5kIHRoZSByZXN1bHQgZm9yIHRoZSBjdXJyZW50IGdyb3VwIHRvIHRoZSBsaXN0DQogICAgcG9vbF92b2x1bWVzX2xpc3RbW2dyb3VwX25hbWVdXSA8LSBwb29sX3ZvbHVtZXNfZGYNCiAgfQ0KICANCiAgIyBDb21iaW5lIGFsbCBzaXRlLXllYXIgcmVzdWx0cyBpbnRvIGEgc2luZ2xlIGRhdGFmcmFtZQ0KICBmaW5hbF9wb29sX3ZvbHVtZXNfZGYgPC0gZG8uY2FsbChyYmluZCwgcG9vbF92b2x1bWVzX2xpc3QpDQogIA0KICByZXR1cm4oZmluYWxfcG9vbF92b2x1bWVzX2RmKQ0KfQ0KDQojIFVzZSBwb29sX3N1bW1hcnlfcmVzdWx0IGZyb20gdGhlIHByZXZpb3VzIHN0ZXAgdG8gZ2V0IHRoZSBzdWJzZXQgb2YgcG9vbCBJRHMNCnBvb2xfdm9sdW1lc19yZXN1bHQgPC0gY2FsY3VsYXRlX3Bvb2xfdm9sdW1lc19mb3Jfc2l0ZXNfeWVhcnMocmVzaWR1YWxzLmRmLCBwb29sX3N1bW1hcnlfcmVzdWx0KQ0KDQojIERpc3BsYXkgdGhlIHJlc3VsdCBhcyBhIHRhYmxlDQpwb29sX3ZvbHVtZXNfcmVzdWx0IDwtIHBvb2xfdm9sdW1lc19yZXN1bHQgJT4lDQogIHNlbGVjdChTaXRlLCB5ZWFyLCBldmVyeXRoaW5nKCkpICAjIE1vdmUgU2l0ZSBhbmQgWWVhciB0byB0aGUgbGVmdA0KZGF0YXRhYmxlKA0KICBwb29sX3ZvbHVtZXNfcmVzdWx0LA0KICBjYXB0aW9uID0gIlBvb2wgVm9sdW1lcyBieSBTaXRlIGFuZCBZZWFyIiwNCiAgcm93bmFtZXMgPSBGQUxTRSwgICMgSGlkZSByb3cgbnVtYmVycw0KICBvcHRpb25zID0gbGlzdCgNCiAgICBwYWdlTGVuZ3RoID0gMTAsICAjIE51bWJlciBvZiByb3dzIHBlciBwYWdlDQogICAgYXV0b1dpZHRoID0gVFJVRQ0KICApDQopJT4lDQogIGZvcm1hdFJvdW5kKGNvbHVtbnMgPSBuYW1lcyhwb29sX3ZvbHVtZXNfcmVzdWx0KVtzYXBwbHkocG9vbF92b2x1bWVzX3Jlc3VsdCwgaXMubnVtZXJpYyldLCBkaWdpdHMgPSAzKQ0KDQojIEV4cG9ydCB0YWJsZQ0KZXhwb3J0X3RhYmxlKGFzLmRhdGEuZnJhbWUocG9vbF92b2x1bWVzX3Jlc3VsdCksICJSZXNpZHVhbCBQb29sIFZvbHVtZSBFc3RpbWF0ZXMuY3N2IikNCmBgYA0KDQpUaGUgYWJvdmUgdGFibGUgbGlzdHMgdGhlIHZvbHVtZSBlc3RpbWF0ZXMgZm9yIGVhY2ggb2YgdGhlICdtZWFuaW5nZnVsJyBzdWJzZXQgb2YgcmVzaWR1YWwgcG9vbHMsIGFuZCB0aGlzIHRhYmxlIGlzIGFsc28gZXhwb3J0ZWQgdG8geW91ciBvdXRwdXQgZm9sZGVyLiBOZXh0IHdlIHdpbGwgZGlzcGxheSBhbmQgZXhwb3J0IGEgdGFibGUgd2l0aCBzb21lIGtleSBzdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIHRoZSByZWFjaDogVG90YWwgdm9sdW1lIG9mIHJlc2lkdWFsIHBvb2xzLCBhbmQgdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiByZXNpZHVhbCB2b2x1bWUgb2YgcG9vbHMuDQoNCmBgYHtyIHBvb2wgdm9sdW1lIHN1bW1hcnkgc3RhdHMsIGVjaG8gPSBGQUxTRX0NCiMgRnVuY3Rpb24gdG8gY2FsY3VsYXRlIHZvbHVtZS1yZWxhdGVkIHN1bW1hcnkgc3RhdGlzdGljcyBmb3IgdGhlIHN1YnNldCBvZiBwb29scw0KY2FsY3VsYXRlX3ZvbHVtZV9zdW1tYXJ5X2Zvcl9zaXRlc195ZWFycyA8LSBmdW5jdGlvbihwb29sX3ZvbHVtZXNfZGYpIHsNCiAgIyBFbnN1cmUgU2l0ZSBhbmQgWWVhciBjb2x1bW5zIGFyZSBwcmVzZW50DQogIGlmICghKCJTaXRlIiAlaW4lIGNvbG5hbWVzKHBvb2xfdm9sdW1lc19kZikpIHx8ICEoInllYXIiICVpbiUgY29sbmFtZXMocG9vbF92b2x1bWVzX2RmKSkpIHsNCiAgICBzdG9wKCJUaGUgZGF0YWZyYW1lIG11c3QgaW5jbHVkZSAnU2l0ZScgYW5kICd5ZWFyJyBjb2x1bW5zLiIpDQogIH0NCiAgDQogICMgU3BsaXQgdGhlIGRhdGEgYnkgU2l0ZSBhbmQgWWVhcg0KICBncm91cGVkX2RhdGEgPC0gc3BsaXQocG9vbF92b2x1bWVzX2RmLCBsaXN0KHBvb2xfdm9sdW1lc19kZiRTaXRlLCBwb29sX3ZvbHVtZXNfZGYkeWVhcikpDQogIA0KICAjIEluaXRpYWxpemUgYSBsaXN0IHRvIHN0b3JlIHN1bW1hcnkgc3RhdGlzdGljcw0KICB2b2x1bWVfc3VtbWFyeV9saXN0IDwtIGxpc3QoKQ0KICANCiAgIyBJdGVyYXRlIG92ZXIgZWFjaCBTaXRlLVllYXIgZ3JvdXANCiAgZm9yIChncm91cF9uYW1lIGluIG5hbWVzKGdyb3VwZWRfZGF0YSkpIHsNCiAgICAjIEdldCB0aGUgY3VycmVudCBncm91cA0KICAgIGdyb3VwIDwtIGdyb3VwZWRfZGF0YVtbZ3JvdXBfbmFtZV1dDQogICAgDQogICAgIyBFeHRyYWN0IFNpdGUgYW5kIFllYXIgKGVuc3VyaW5nIHVuaXF1ZW5lc3MpDQogICAgc2l0ZSA8LSB1bmlxdWUoZ3JvdXAkU2l0ZSkNCiAgICB5ZWFyIDwtIHVuaXF1ZShncm91cCR5ZWFyKQ0KICAgIA0KICAgICMgQ2hlY2sgZm9yIHZhbGlkIFNpdGUgYW5kIFllYXINCiAgICBpZiAobGVuZ3RoKHNpdGUpICE9IDEgfHwgbGVuZ3RoKHllYXIpICE9IDEgfHwgaXMubmEoc2l0ZSkgfHwgaXMubmEoeWVhcikpIHsNCiAgICAgIHdhcm5pbmcoc3ByaW50ZigiSW52YWxpZCBTaXRlIG9yIFllYXIgaW4gZ3JvdXA6ICVzLiBTa2lwcGluZy4uLiIsIGdyb3VwX25hbWUpKQ0KICAgICAgbmV4dA0KICAgIH0NCiAgICANCiAgICAjIENhbGN1bGF0ZSB0b3RhbCByZXNpZHVhbCBwb29sIHZvbHVtZQ0KICAgIHRvdGFsX3Jlc2lkdWFsX3ZvbHVtZSA8LSBzdW0oZ3JvdXAkcG9vbF92b2x1bWVfbTMsIG5hLnJtID0gVFJVRSkNCiAgICANCiAgICAjIENhbGN1bGF0ZSBtZWFuIHJlc2lkdWFsIHBvb2wgdm9sdW1lDQogICAgbWVhbl9yZXNpZHVhbF92b2x1bWUgPC0gbWVhbihncm91cCRwb29sX3ZvbHVtZV9tMywgbmEucm0gPSBUUlVFKQ0KICAgIA0KICAgICMgQ2FsY3VsYXRlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiByZXNpZHVhbCBwb29sIHZvbHVtZQ0KICAgIHNkX3Jlc2lkdWFsX3ZvbHVtZSA8LSBzZChncm91cCRwb29sX3ZvbHVtZV9tMywgbmEucm0gPSBUUlVFKQ0KICAgIA0KICAgICMgQ3JlYXRlIGEgc3VtbWFyeSB0YWJsZSBmb3IgdGhlIGN1cnJlbnQgU2l0ZS1ZZWFyDQogICAgdm9sdW1lX3N1bW1hcnkgPC0gZGF0YS5mcmFtZSgNCiAgICAgIFNpdGUgPSBzaXRlLA0KICAgICAgeWVhciA9IHllYXIsDQogICAgICB0b3RhbF9yZXNpZHVhbF92b2x1bWUgPSB0b3RhbF9yZXNpZHVhbF92b2x1bWUsDQogICAgICBtZWFuX3Jlc2lkdWFsX3ZvbHVtZSA9IG1lYW5fcmVzaWR1YWxfdm9sdW1lLA0KICAgICAgc2RfcmVzaWR1YWxfdm9sdW1lID0gc2RfcmVzaWR1YWxfdm9sdW1lDQogICAgKQ0KICAgIA0KICAgICMgQXBwZW5kIHRoZSBzdW1tYXJ5IHRvIHRoZSBsaXN0DQogICAgdm9sdW1lX3N1bW1hcnlfbGlzdFtbZ3JvdXBfbmFtZV1dIDwtIHZvbHVtZV9zdW1tYXJ5DQogIH0NCiAgDQogICMgQ29tYmluZSBhbGwgU2l0ZS1ZZWFyIHN1bW1hcmllcyBpbnRvIGEgc2luZ2xlIGRhdGFmcmFtZQ0KICBmaW5hbF92b2x1bWVfc3VtbWFyeV9kZiA8LSBkby5jYWxsKHJiaW5kLCB2b2x1bWVfc3VtbWFyeV9saXN0KQ0KICANCiAgcmV0dXJuKGZpbmFsX3ZvbHVtZV9zdW1tYXJ5X2RmKQ0KfQ0KDQojIENhbGN1bGF0ZSB0aGUgc3VtbWFyeSBzdGF0aXN0aWNzIGZvciB0aGUgc3Vic2V0IG9mIHBvb2xzIGJhc2VkIG9uIHRoZWlyIHZvbHVtZXMNCnZvbHVtZV9zdW1tYXJ5X3Jlc3VsdCA8LSBjYWxjdWxhdGVfdm9sdW1lX3N1bW1hcnlfZm9yX3NpdGVzX3llYXJzKHBvb2xfdm9sdW1lc19yZXN1bHQpDQoNCiMgRGlzcGxheSB0aGUgcmVzdWx0IGFzIGEgdGFibGUNCnZvbHVtZV9zdW1tYXJ5X3Jlc3VsdCA8LSB2b2x1bWVfc3VtbWFyeV9yZXN1bHQgJT4lDQogIHNlbGVjdChTaXRlLCB5ZWFyLCBldmVyeXRoaW5nKCkpICAjIE1vdmUgU2l0ZSBhbmQgWWVhciB0byB0aGUgbGVmdA0KZGF0YXRhYmxlKA0KICB2b2x1bWVfc3VtbWFyeV9yZXN1bHQsDQogIGNhcHRpb24gPSAiVm9sdW1lIFN1bW1hcnkgU3RhdGlzdGljcyBmb3IgU3Vic2V0IG9mIFBvb2xzIGJ5IFNpdGUgYW5kIFllYXIiLA0KICByb3duYW1lcyA9IEZBTFNFLCAgIyBIaWRlIHJvdyBudW1iZXJzDQogIG9wdGlvbnMgPSBsaXN0KA0KICAgIHBhZ2VMZW5ndGggPSAxMCwgICMgTnVtYmVyIG9mIHJvd3MgcGVyIHBhZ2UNCiAgICBhdXRvV2lkdGggPSBUUlVFDQogICkNCiklPiUNCiAgZm9ybWF0Um91bmQoY29sdW1ucyA9IG5hbWVzKHZvbHVtZV9zdW1tYXJ5X3Jlc3VsdClbc2FwcGx5KHZvbHVtZV9zdW1tYXJ5X3Jlc3VsdCwgaXMubnVtZXJpYyldLCBkaWdpdHMgPSAzKQ0KDQojIEV4cG9ydCB0YWJsZQ0KZXhwb3J0X3RhYmxlKGFzLmRhdGEuZnJhbWUodm9sdW1lX3N1bW1hcnlfcmVzdWx0KSwgIlJlYWNoIFJlc2lkdWFsIFBvb2wgVm9sdW1lIE1ldHJpY3MgYnkgU2l0ZSBhbmQgWWVhci5jc3YiKQ0KYGBgDQoNCiMjIEluZmVyZW50aWFsIFRlc3RzIC0gVm9sdW1lDQoNCkZvbGxvd2luZyB0aGUgc2FtZSBhcHByb2FjaCBhcyBmb3IgdGhlIG9uZS0gYW5kIHR3by1kaW1lbnNpb25hbCBwb29sIG1ldHJpY3MsIHdlIHdpbGwgdXNlIEFOT1ZBcyB0byB0ZXN0IHRoZSBwb29sIHZvbHVtZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHNpdGVzIGFuZCB5ZWFycy4NCg0KIyMgQXNzdW1wdGlvbiBSb2J1c3RuZXNzDQoNCkFzIGJlZm9yZSwgdGhlIGZpcnN0IHN0ZXAgaXMgdG8gY2hlY2sgd2hldGhlciBhbiBBTk9WQSBpcyBzdWl0YWJsZSBmb3IgdGhlIHZhcmlhYmxlcy4NCg0KYGBge3Igdm9sdW1lIGRhdGEgZXZhbHVhdGluZywgZWNobz1GQUxTRX0NCiMjIyMgYWRkIHRoZSBiZWZvcmUvYWZ0ZXIgY2F0ZWdvcmllcyBmcm9tIHByZXZpb3VzIGlucHV0DQpwb29sX3ZvbHVtZXNfcmVzdWx0IDwtIHBvb2xfdm9sdW1lc19yZXN1bHQgJT4lDQogIG11dGF0ZShUaW1lX0NhdGVnb3J5ID0gY2FzZV93aGVuKA0KICAgIHllYXIgJWluJSBiZWZvcmVfeWVhcnMgfiAiQmVmb3JlIiwNCiAgICB5ZWFyICVpbiUgYWZ0ZXJfeWVhcnMgfiAiQWZ0ZXIiLA0KICAgIFRSVUUgfiBOQV9jaGFyYWN0ZXJfDQogICkpDQoNCiMgRmlsdGVyIG91dCBzaXRlcyB3aXRob3V0IGJvdGggdGltZSBjYXRlZ29yaWVzLiBSZW1vdmUgcm93cyB3aXRoIHBvb2xfaWQgPSAiVG90YWwiDQpwb29sX3ZvbHVtZXNfZmlsdGVyZWQgPC0gcG9vbF92b2x1bWVzX3Jlc3VsdCAlPiUNCiAgZmlsdGVyKHBvb2xfaWQgIT0gIlRvdGFsIikgJT4lDQogIGdyb3VwX2J5KFNpdGUpICU+JQ0KICBmaWx0ZXIoYWxsKGMoIkJlZm9yZSIsICJBZnRlciIpICVpbiUgVGltZV9DYXRlZ29yeSkpICU+JQ0KICB1bmdyb3VwKCkNCg0KIyMjIyMjIyMjIyMjIyMgU2hhcGlybyBXaWxrIE5vcm1hbGl0eSBUZXN0DQp0ZXN0X25vcm1hbGl0eV92b2x1bWVzIDwtIGZ1bmN0aW9uKHBvb2xfdm9sdW1lc19kZikgew0KICBwb29sX3ZvbHVtZXNfZ3JvdXBlZCA8LSBzcGxpdChwb29sX3ZvbHVtZXNfZGYsIGxpc3QocG9vbF92b2x1bWVzX2RmJFNpdGUsIHBvb2xfdm9sdW1lc19kZiRUaW1lX0NhdGVnb3J5KSkNCiAgbm9ybWFsaXR5X3Jlc3VsdHNfbGlzdCA8LSBsaXN0KCkNCiAgDQogIGZvciAoZ3JvdXBfbmFtZSBpbiBuYW1lcyhwb29sX3ZvbHVtZXNfZ3JvdXBlZCkpIHsNCiAgICBncm91cCA8LSBwb29sX3ZvbHVtZXNfZ3JvdXBlZFtbZ3JvdXBfbmFtZV1dDQogICAgaWYgKG5yb3coZ3JvdXApIDwgMykgew0KICAgICAgbm9ybWFsaXR5X3Jlc3VsdHNfbGlzdFtbZ3JvdXBfbmFtZV1dIDwtIGRhdGEuZnJhbWUoDQogICAgICAgIFNpdGUgPSBOQSwgVGltZV9DYXRlZ29yeSA9IE5BLA0KICAgICAgICBwb29sX3ZvbHVtZV9tM19wX3ZhbHVlID0gTkEsDQogICAgICAgIG1lc3NhZ2UgPSAiTm90IGVub3VnaCBkYXRhIGZvciBub3JtYWxpdHkgdGVzdCINCiAgICAgICkNCiAgICAgIG5leHQNCiAgICB9DQogICAgcG9vbF92b2x1bWVfdGVzdCA8LSBzaGFwaXJvLnRlc3QoZ3JvdXAkcG9vbF92b2x1bWVfbTMpDQogICAgDQogICAgbm9ybWFsaXR5X3Jlc3VsdHNfbGlzdFtbZ3JvdXBfbmFtZV1dIDwtIGRhdGEuZnJhbWUoDQogICAgICBTaXRlID0gdW5pcXVlKGdyb3VwJFNpdGUpLA0KICAgICAgVGltZV9DYXRlZ29yeSA9IHVuaXF1ZShncm91cCRUaW1lX0NhdGVnb3J5KSwNCiAgICAgIHBvb2xfdm9sdW1lX20zX3BfdmFsdWUgPSBwb29sX3ZvbHVtZV90ZXN0JHAudmFsdWUsDQogICAgICBtZXNzYWdlID0gIk5vcm1hbGl0eSB0ZXN0IGNvbXBsZXRlZCINCiAgICApDQogIH0NCiAgbm9ybWFsaXR5X3Jlc3VsdHNfZGYgPC0gZG8uY2FsbChyYmluZCwgbm9ybWFsaXR5X3Jlc3VsdHNfbGlzdCkNCiAgcmV0dXJuKG5vcm1hbGl0eV9yZXN1bHRzX2RmKQ0KfQ0KDQojIFRlc3Qgbm9ybWFsaXR5IGZvciBwb29sIHZvbHVtZXMNCm5vcm1hbGl0eV9yZXN1bHRzX3ZvbHVtZXMgPC0gdGVzdF9ub3JtYWxpdHlfdm9sdW1lcyhwb29sX3ZvbHVtZXNfZmlsdGVyZWQpDQojIGRpc3BsYXkgaW4gdGFibGUNCm5vcm1hbGl0eV9yZXN1bHRzX3ZvbHVtZXMgJT4lDQogIG11dGF0ZSgNCiAgICBwb29sX3ZvbHVtZV9tM19wX3ZhbHVlID0gcm91bmQocG9vbF92b2x1bWVfbTNfcF92YWx1ZSwgMykNCiAgKSAlPiUNCiAga2FibGUoDQogICAgY2FwdGlvbiA9ICJOb3JtYWxpdHkgVGVzdCBSZXN1bHRzIGZvciBQb29sIFZvbHVtZSBEYXRhIiwNCiAgICBjb2wubmFtZXMgPSBjKCJTaXRlIiwgIlRpbWUgQ2F0ZWdvcnkiLCANCiAgICAgICAgICAgICAgICAgICJQb29sIFZvbHVtZSBQLVZhbHVlIiwgDQogICAgICAgICAgICAgICAgICAiTWVzc2FnZSIpLA0KICAgIGFsaWduID0gImMiLCAgIyBDZW50ZXItYWxpZ24gdGhlIGNvbHVtbnMNCiAgICByb3cubmFtZXMgPSBGQUxTRQ0KICApICMgbG9vayBvdXQgZm9yIHAgdmFsdWVzIDwwLjA1IHdoaWNoIGluZGljYXRlIG5vbi1ub3JtYWxpdHkNCg0KIyMjIyMjIyMjIyMjIyMjIExldmVuZXMgdGVzdCBmb3IgZXF1YWxpdHkgb2YgdmFyaWFuY2UNCnJ1bl9sZXZlbmVzX3Rlc3Rfdm9sdW1lcyA8LSBmdW5jdGlvbihwb29sX3ZvbHVtZXNfZGYpIHsNCiAgIyBMZXZlbmUncyB0ZXN0IGZvciBwb29sIHZvbHVtZXMNCiAgbGV2ZW5lX3Rlc3QgPC0gbGV2ZW5lVGVzdChwb29sX3ZvbHVtZV9tMyB+IGludGVyYWN0aW9uKFNpdGUsIHllYXIpLCBkYXRhID0gcG9vbF92b2x1bWVzX2RmKQ0KICByZXR1cm4obGV2ZW5lX3Rlc3QpDQp9DQoNCiMgUnVuIExldmVuZSdzIHRlc3QgZm9yIHBvb2wgdm9sdW1lcw0KbGV2ZW5lX3Jlc3VsdHNfdm9sdW1lcyA8LSBydW5fbGV2ZW5lc190ZXN0X3ZvbHVtZXMocG9vbF92b2x1bWVzX2ZpbHRlcmVkKQ0KcHJpbnQobGV2ZW5lX3Jlc3VsdHNfdm9sdW1lcykNCg0KIyMjIyMjIyMjIyMjIyMjIyMgRnVuY3Rpb24gdG8gZ2VuZXJhdGUgYWRkaXRpb25hbCBkaWFnbm9zdGljcyBmb3IgcG9vbCB2b2x1bWVzDQpnZW5lcmF0ZV9hc3N1bXB0aW9uX2RpYWdub3N0aWNzIDwtIGZ1bmN0aW9uKHBvb2xfdm9sdW1lc19kZikgew0KICAjIFEtUSBwbG90DQogIHFxX3Bsb3QgPC0gZ2dwbG90KHBvb2xfdm9sdW1lc19kZiwgYWVzKHNhbXBsZSA9IHBvb2xfdm9sdW1lX20zKSkgKw0KICAgIGdlb21fcXEoKSArDQogICAgZ2VvbV9xcV9saW5lKCkgKw0KICAgIGdndGl0bGUoIlEtUSBQbG90IGZvciBQb29sIFZvbHVtZSAobTMpIikNCiAgDQogICMgU2tld25lc3MgYW5kIEt1cnRvc2lzDQogIHNrZXdfdmFsdWUgPC0gc2tld25lc3MocG9vbF92b2x1bWVzX2RmJHBvb2xfdm9sdW1lX20zLCBuYS5ybSA9IFRSVUUpDQogIGt1cnRfdmFsdWUgPC0ga3VydG9zaXMocG9vbF92b2x1bWVzX2RmJHBvb2xfdm9sdW1lX20zLCBuYS5ybSA9IFRSVUUpDQogIA0KICAjIEJveHBsb3QNCiAgYm94cGxvdCA8LSBnZ3Bsb3QocG9vbF92b2x1bWVzX2RmLCBhZXMoeCA9IFNpdGUsIHkgPSBwb29sX3ZvbHVtZV9tMywgZmlsbCA9IFRpbWVfQ2F0ZWdvcnkpKSArDQogICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgIGxhYnModGl0bGUgPSAiQm94cGxvdCBvZiBQb29sIFZvbHVtZSBieSBTaXRlIGFuZCBUaW1lIENhdGVnb3J5IikgKw0KICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQogIA0KICAjIFJldHVybiBhbGwgZGlhZ25vc3RpY3MNCiAgcmV0dXJuKGxpc3QoDQogICAgYm94cGxvdCA9IGJveHBsb3QsDQogICAgcXFfcGxvdCA9IHFxX3Bsb3QsDQogICAgc2tld25lc3MgPSBza2V3X3ZhbHVlLA0KICAgIGt1cnRvc2lzID0ga3VydF92YWx1ZQ0KICApKQ0KfQ0KDQojIyMjIEFwcGx5IHRvIHBvb2xfdm9sdW1lc19maWx0ZXJlZA0KZGlhZ25vc3RpY3MgPC0gZ2VuZXJhdGVfYXNzdW1wdGlvbl9kaWFnbm9zdGljcyhwb29sX3ZvbHVtZXNfZmlsdGVyZWQpDQoNCiMjIyMgUHJpbnQgcmVzdWx0cw0KcHJpbnQoZGlhZ25vc3RpY3MkYm94cGxvdCkNCnByaW50KGRpYWdub3N0aWNzJHFxX3Bsb3QpDQpjYXQoIlNrZXduZXNzOiIsIGRpYWdub3N0aWNzJHNrZXduZXNzLCAiXG4iKQ0KY2F0KCJLdXJ0b3NpczoiLCBkaWFnbm9zdGljcyRrdXJ0b3NpcywgIlxuIikNCmBgYA0KV2UgbmVlZGVkIHRvIHRyYW5zZm9ybSBvdXIgdm9sdW1lIGRhdGEsIHdoaWNoIHdhcyBub3Qgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIEZvbGxvd2luZyB0aGUgc2FtZSB0cmFuc2Zvcm1hdGlvbiBzdGVwcyBhcyBiZWZvcmUsIFdlIHJlcGxhY2VkICdwb29sX3ZvbHVtZV9tMycgd2l0aCB0aGUgbG9nLXRyYW5zZm9ybWVkICd0cmFuc2Zvcm1lZF9wb29sX3ZvbHVtZV9tMycgKHVzaW5nIHRoZSBiZWxvdyBjb2RlKSBhbmQgcmUtcmFuIHRoZSBkaWFnbm9zdGljcy4gT3VyIFEtUSBwbG90IGFuZCB0ZXN0cyBsb29rZWQgbXVjaCBiZXR0ZXIsIHNvIHdlIHVzZWQgdGhlIHRyYW5zZm9ybWVkIHZhcmlhYmxlIGluIHRoZSBBTk9WQS4NCg0KYGBge3Igdm9sdW1lIHRyYW5zZm9ybWF0aW9ufQ0KIyBEZWZpbmUgdHJhbnNmb3JtYXRpb25zIGFzIGEgbmFtZWQgbGlzdCBmb3IgcG9vbCB2b2x1bWUNCnRyYW5zZm9ybWF0aW9ucyA8LSBsaXN0KA0KICBwb29sX3ZvbHVtZV9tMyA9IGZ1bmN0aW9uKHgpIGlmZWxzZSh4ID4gMCwgbG9nKHgpLCBOQSkgICMgTG9nIHRyYW5zZm9ybWF0aW9uIHdpdGggaGFuZGxpbmcgZm9yIG5vbi1wb3NpdGl2ZSB2YWx1ZXMgKHZvbHVtZXMgc2hvdWxkIGFsbCBiZSBwb3NpdGl2ZSEpDQopDQoNCiMgQXBwbHkgdHJhbnNmb3JtYXRpb25zIGFuZCB1cGRhdGUgdGhlIGRhdGFmcmFtZQ0KcG9vbF92b2x1bWVzX2ZpbHRlcmVkIDwtIGFwcGx5X3RyYW5zZm9ybWF0aW9ucyhwb29sX3ZvbHVtZXNfZmlsdGVyZWQsIHRyYW5zZm9ybWF0aW9ucykNCmBgYA0KIyMgQU5PVkEgLSB2b2x1bWUgDQoNCmBgYHtyIGluZmVyZW50aWFsIHRlc3RzIHZvbH0NCiMgRW5zdXJlIHRyYW5zZm9ybWVkIGRhdGEgaXMgdXNlZCBpbiB0aGUgQU5PVkEgZnVuY3Rpb24gaWYgbmVjZXNzYXJ5IChjaGFuZ2UgdGhlIHZhcmlhYmxlIG5hbWUgaW4gcXVvdGF0aW9uIG1hcmtzKQ0KYW5vdmFfcG9vbF92b2x1bWVzIDwtIHJ1bl9hbm92YShwb29sX3ZvbHVtZXNfZmlsdGVyZWQsICJwb29sX3ZvbHVtZV9tMyIpICMgYWRqdXN0IHRvICJ0cmFuc2Zvcm1lZF9wb29sX3ZvbHVtZXNfbTMiIGFzIG5lZWRlZA0KYGBgDQpgYGB7ciBwcmludCB2b2wgQU5PVkFzLCBlY2hvID0gRkFMU0V9DQojcHJpbnQgcmVzdWx0cw0KcHJpbnQoYW5vdmFfcG9vbF92b2x1bWVzKQ0KDQojIGV4cG9ydCB0ZXN0IHN1bW1hcnkNCnZvbF9vdXRwdXQgPC0gY2FwdHVyZS5vdXRwdXQocHJpbnQoYW5vdmFfcG9vbF92b2x1bWVzKSkgICMgQ2FwdHVyZSB0aGUgcHJpbnRlZCBvdXRwdXQNCnN1bW1hcnlfdGV4dCA8LSBjKCJBTk9WQSBmb3IgUmVzaWR1YWwgUG9vbCBWb2x1bWUiLCB2b2xfb3V0cHV0KQ0KZXhwb3J0X3N1bW1hcnkoc3VtbWFyeV90ZXh0LCAiUmVzaWR1YWwgUG9vbCBWb2x1bWUgQU5PVkEiKQ0KYGBgDQpXaGVuIGludGVycHJldGluZyBwb3RlbnRpYWwgY2hhbmdlcyBpbiBwb29sIHZvbHVtZSBtZXRyaWNzLCByZW1lbWJlciB0aGF0IHdlIG5lZWRlZCB0byBtYWtlIGFzc3VtcHRpb25zIHJlZ2FyZGluZyB0aGUgd2lkdGhzIG9mIHJlc2lkdWFsIHBvb2xzLCBtYWtpbmcgdGhlc2Ugdm9sdW1lIG1ldHJpY3MgbW9yZSBzcGVjdWxhdGl2ZSB0aGFuIHNhZ2l0dGFsIGFyZWEgbWV0cmljcy4gV2hpbGUgdm9sdW1lcyBjYW4gYmUgdXNlZnVsIGZvciBpbnRlcnByZXRhdGlvbiwgaWYgdGhlcmUgYXJlIGRpc2FncmVlbWVudHMgYmV0d2VlbiB0aGUgaW5mZXJlbnRpYWwgdGVzdCByZXN1bHRzIGFtb25nIHZvbHVtZS0gYW5kIGFyZWEvbGVuZ3RoLWJhc2VkIG1ldHJpY3MsIHdlIHJlY29tbWVuZCBkZWZhdWx0aW5nIHRvIHRoZSBsYXR0ZXIgKHVubGVzcywgb2YgY291cnNlLCB5b3UgaGF2ZSBhIHNvbGlkIF9hIHByaW9yaV8gaHlwb3RoZXNpcyBhbmQgcHJlZGljdGlvbiB0aGF0IHN1Z2dlc3RzIHZvbHVtZSBzaG91bGQgZGlmZmVyIGluIHRoZSB3YXkgeW91IG9ic2VydmVkKS4NCg0KIyBGaW5lIFNlZGltZW50IGluIFBvb2xzDQoNClRoZSBsb25naXR1ZGluYWwgc3VydmV5IGluY2x1ZGVkIHByZXNlbmNlL2Fic2VuY2Ugb2JzZXJ2YXRpb25zIG9mIGZpbmUgc2VkaW1lbnQgYWxvbmcgdGhlIHRoYWx3ZWcuIEhlcmUgd2Ugd2lsbCBnZW5lcmF0ZSBhIG1ldHJpYyBvZiB0aGUgcHJvcG9ydGlvbiBvZiByZXNpZHVhbCBwb29sIHRoYWx3ZWcgdGhhdCBmZWF0dXJlcyBmaW5lIHNlZGltZW50cy4gDQoNCk5vdGUgdGhhdCwgd2hpbGUgdGhlIHByZXZpb3VzIG1ldHJpY3MgaW4gdGhpcyBzY3JpcHQgdXNlIHRoZSAnY3VzdG9tIGRlcHRoJyB0aHJlc2hvbGQgdG8gc3Vic2V0IHdoYXQgYXJlIGNvbnNpZGVyZWQgJ21lYW5pbmdmdWwnIHBvb2xzLCB3ZSByZWNvbW1lbmQgY29uc2lkZXJpbmcgZmluZSBzZWRpbWVudCByZWxhdGl2ZSB0byB0aGUgZnVsbCBjb250aW5nZW50IG9mIHJlc2lkdWFsIHBvb2xzIHRoYXQgdGhlIGNvZGUgaGFzIGlkZW50aWZpZWQuIE91ciByYXRpb25hbGUgaXMgdGhhdCB0aGUgZmluZXMgbWV0cmljcyByZWxhdGUgbW9yZSBjbG9zZWx5IHRvIHRoZSBtZWNoYW5pc21zIHRoYXQgY2FuIGJlIHJlc3BvbnNpYmxlIGZvciBtYWtpbmcgcG9vbHMgJ21lYW5pbmdmdWwnIChvciBub3QpIGluIHRlcm1zIG9mIGZpc2ggaGFiaXRhdCBhdmFpbGFiaWxpdHkuIElmIHdlIHdlcmUgdG8gbG9vayBhdCB0aGUgcHJvcG9ydGlvbiBvZiBmaW5lcyBvbmx5IGluICdtZWFuaW5nZnVsJyAoZGVlcCBlbm91Z2gpIHBvb2xzLCB3ZSBtaWdodCBtaXNzIHBvb2xzIHRoYXQgYXJlIGNsb3NlciB0byBiZWluZyAnbm90IHBvb2xzJyAoaS5lLiwgcmVjZW50bHkgZmlsbGluZy1pbiBvciBzY291cmluZyBvZiBzZWRpbWVudCkuIE9mIGNvdXJzZSwgd2hlbiBwb29scyBhcmUgZnVsbHkgaW5maWxsZWQgd2l0aCBzZWRpbWVudCB0aGV5IHdpbGwgbm90IGJlIGRldGVjdGVkIGFzIHBvb2xzIGF0IGFsbCwgYnV0IHRoZSBhYmlsaXR5IHRvIHJlY29nbmlzZSB3aGVuIGEgcG9vbCBpcyBmaWxsaW5nIGluIChvciBzY291cmluZyBvdXQpIG1heSBiZSBhbiBpbXBvcnRhbnQgaW5kaWNhdG9yIG9mIHJlc3RvcmF0aW9uIHN1Y2Nlc3MsIG9yIGEgdHJpZ2dlciBmb3IgYWRhcHRpdmUgbWFuYWdlbWVudCBhY3Rpb25zLg0KDQpgYGB7ciBmaW5lcywgZWNobyA9IEZBTFNFfQ0KY2FsY3VsYXRlX2ZpbmVzX3Byb3BvcnRpb24gPC0gZnVuY3Rpb24ocG9vbF9kYXRhLCByZXNpZHVhbHMuZGYsIGN1c3RvbV9kZXB0aF90aHJlc2hvbGQgPSBOVUxMLCB1c2Vfc2RfdGhyZXNob2xkID0gRkFMU0UpIHsNCiAgIyBFbnN1cmUgdGhlIHJlc2lkdWFscyBkYXRhZnJhbWUgaGFzICdTaXRlJyBhbmQgJ3llYXInIGNvbHVtbnMgZm9yIGdyb3VwaW5nDQogIGlmICghYWxsKGMoIlNpdGUiLCAieWVhciIpICVpbiUgY29sbmFtZXMocmVzaWR1YWxzLmRmKSkpIHsNCiAgICBzdG9wKCJyZXNpZHVhbHMuZGYgbXVzdCBjb250YWluICdTaXRlJyBhbmQgJ3llYXInIGNvbHVtbnMuIikNCiAgfQ0KICANCiAgIyBJbml0aWFsaXplIGEgbGlzdCB0byBzdG9yZSByZXN1bHRzDQogIGZpbmVzX3Byb3BvcnRpb25fbGlzdCA8LSBsaXN0KCkNCiAgDQogICMgR3JvdXAgcmVzaWR1YWxzIGJ5IFNpdGUgYW5kIHllYXINCiAgdW5pcXVlX3NpdGVzX3llYXJzIDwtIHVuaXF1ZShyZXNpZHVhbHMuZGZbYygiU2l0ZSIsICJ5ZWFyIildKQ0KICANCiAgZm9yIChpIGluIDE6bnJvdyh1bmlxdWVfc2l0ZXNfeWVhcnMpKSB7DQogICAgc2l0ZSA8LSB1bmlxdWVfc2l0ZXNfeWVhcnMkU2l0ZVtpXQ0KICAgIHllYXIgPC0gdW5pcXVlX3NpdGVzX3llYXJzJHllYXJbaV0NCiAgICANCiAgICAjIFN1YnNldCB0aGUgcmVzaWR1YWxzIGRhdGFmcmFtZSBmb3IgdGhlIGN1cnJlbnQgU2l0ZSBhbmQgeWVhcg0KICAgIHN1YnNldF9yZXNpZHVhbHMgPC0gcmVzaWR1YWxzLmRmW3Jlc2lkdWFscy5kZiRTaXRlID09IHNpdGUgJiByZXNpZHVhbHMuZGYkeWVhciA9PSB5ZWFyLCBdDQogICAgDQogICAgICAgIGlmIChucm93KHN1YnNldF9yZXNpZHVhbHMpID09IDAgfHwgYWxsKGlzLm5hKHN1YnNldF9yZXNpZHVhbHMkcmVzaWR1YWxfZGVwdGgpKSkgew0KICAgIG1lc3NhZ2UocGFzdGUoIlNraXBwaW5nIFNpdGU6Iiwgc2l0ZSwgIlllYXI6IiwgeWVhciwgDQogICAgICAgICAgICAgICAgICAiLSBubyB2YWxpZCByZXNpZHVhbCBkZXB0aCBkYXRhIGF2YWlsYWJsZS4iKSkNCiAgICBuZXh0DQp9DQogICAgIyBFbnN1cmUgdGhlIGRhdGFmcmFtZSBpcyBzb3J0ZWQgYnkgZGlzdGFuY2Ugd2l0aGluIGVhY2ggcG9vbA0KICAgIHN1YnNldF9yZXNpZHVhbHMgPC0gc3Vic2V0X3Jlc2lkdWFsc1tvcmRlcihzdWJzZXRfcmVzaWR1YWxzJHBvb2xfaWQsIHN1YnNldF9yZXNpZHVhbHMkZGlzdGFuY2UpLCBdDQogICAgDQogICAgIyBUcmltIHdoaXRlc3BhY2UgZnJvbSB0aGUgRmluZXMgY29sdW1uDQogICAgc3Vic2V0X3Jlc2lkdWFscyRGaW5lcyA8LSB0cmltd3Moc3Vic2V0X3Jlc2lkdWFscyRGaW5lcykNCiAgICANCiAgICAjIEluaXRpYWxpemUgYSBsaXN0IHRvIHN0b3JlIHJlc3VsdHMgZm9yIHRoZSBjdXJyZW50IFNpdGUveWVhcg0KICAgIGZpbmVzX3Byb3BvcnRpb25fc2l0ZV95ZWFyIDwtIGxpc3QoKQ0KICAgIA0KICAgICMgQ2FsY3VsYXRlIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgcmVzaWR1YWwgZGVwdGggaWYgbmVlZGVkDQogICAgaWYgKHVzZV9zZF90aHJlc2hvbGQpIHsNCiAgICAgIHNkX3Jlc2lkdWFsX2RlcHRoIDwtIHNkKHN1YnNldF9yZXNpZHVhbHMkcmVzaWR1YWxfZGVwdGgsIG5hLnJtID0gVFJVRSkNCiAgICB9DQogICAgDQogICAgIyBJdGVyYXRlIG92ZXIgZWFjaCB1bmlxdWUgcG9vbF9pZA0KICAgIHVuaXF1ZV9wb29sX2lkcyA8LSB1bmlxdWUoc3Vic2V0X3Jlc2lkdWFscyRwb29sX2lkKQ0KICAgIGZvciAocG9vbF9pZCBpbiB1bmlxdWVfcG9vbF9pZHMpIHsNCiAgICAgICMgU2tpcCBpZiBwb29sX2lkIGlzIE5BDQogIGlmIChpcy5uYShwb29sX2lkKSkgew0KICAgIG5leHQNCiAgfQ0KICAgICAgIyBTdWJzZXQgZGF0YSBmb3IgdGhlIGN1cnJlbnQgcG9vbA0KICAgICAgcG9vbF9yZXNpZHVhbHMgPC0gc3Vic2V0X3Jlc2lkdWFsc1tzdWJzZXRfcmVzaWR1YWxzJHBvb2xfaWQgPT0gcG9vbF9pZCwgXQ0KICAgICAgDQogICAgICAgIyBFbnN1cmUgdGhlcmUgaXMgZGF0YSBiZWZvcmUgY2FsY3VsYXRpbmcgdGhlIG1heGltdW0gcmVzaWR1YWwgZGVwdGgNCiAgaWYgKG5yb3cocG9vbF9yZXNpZHVhbHMpID09IDAgfHwgYWxsKGlzLm5hKHBvb2xfcmVzaWR1YWxzJHJlc2lkdWFsX2RlcHRoKSkpIHsNCiAgICBtZXNzYWdlKHBhc3RlKCJTa2lwcGluZyBQb29sOiIsIHBvb2xfaWQsICJTaXRlOiIsIHNpdGUsICJZZWFyOiIsIHllYXIsICItIG5vIHZhbGlkIHJlc2lkdWFsIGRlcHRoIGRhdGEgYXZhaWxhYmxlLiIpKQ0KICAgIG5leHQNCiAgfQ0KICAgICAgIyBDYWxjdWxhdGUgdGhlIG1heGltdW0gcmVzaWR1YWwgZGVwdGgNCiAgICAgIG1heF9yZXNpZHVhbF9kZXB0aCA8LSBtYXgocG9vbF9yZXNpZHVhbHMkcmVzaWR1YWxfZGVwdGgsIG5hLnJtID0gVFJVRSkNCiAgICAgIA0KICAgICAgIyBBcHBseSBzZWxlY3Rpb24gY3JpdGVyaWE6IGVpdGhlciB0aGUgbWF4IHJlc2lkdWFsIGRlcHRoIGlzID49IHNkIG9yIHRoZSBjdXN0b20gdGhyZXNob2xkIGlzIG1ldA0KICAgICAgaWYgKCFpcy5udWxsKGN1c3RvbV9kZXB0aF90aHJlc2hvbGQpKSB7DQogICAgICAgIGlmIChtYXhfcmVzaWR1YWxfZGVwdGggPCBjdXN0b21fZGVwdGhfdGhyZXNob2xkKSB7DQogICAgICAgICAgbmV4dCAgIyBTa2lwIHRoaXMgcG9vbCBpZiBpdCBkb2Vzbid0IG1lZXQgdGhlIGN1c3RvbSB0aHJlc2hvbGQNCiAgICAgICAgfQ0KICAgICAgfSBlbHNlIGlmICh1c2Vfc2RfdGhyZXNob2xkICYmIG1heF9yZXNpZHVhbF9kZXB0aCA8IHNkX3Jlc2lkdWFsX2RlcHRoKSB7DQogICAgICAgIG5leHQgICMgU2tpcCB0aGlzIHBvb2wgaWYgaXQgZG9lc24ndCBtZWV0IHRoZSBTRCB0aHJlc2hvbGQNCiAgICAgIH0NCiAgICAgIA0KICAgICAgIyBJbml0aWFsaXplIGEgY29sdW1uIGZvciBzZWdtZW50IGxlbmd0aHMNCiAgICAgIHBvb2xfcmVzaWR1YWxzJHNlZ21lbnRfbGVuZ3RoIDwtIE5BDQogICAgICANCiAgICAgICMgQ2FsY3VsYXRlIHNlZ21lbnQgbGVuZ3Rocw0KICAgICAgZm9yIChpIGluIDE6bnJvdyhwb29sX3Jlc2lkdWFscykpIHsNCiAgICAgICAgaWYgKGkgPT0gMSkgew0KICAgICAgICAgIHBvb2xfcmVzaWR1YWxzJHNlZ21lbnRfbGVuZ3RoW2ldIDwtIChwb29sX3Jlc2lkdWFscyRkaXN0YW5jZVtpICsgMV0gLSBwb29sX3Jlc2lkdWFscyRkaXN0YW5jZVtpXSkgLyAyDQogICAgICAgIH0gZWxzZSBpZiAoaSA9PSBucm93KHBvb2xfcmVzaWR1YWxzKSkgew0KICAgICAgICAgIHBvb2xfcmVzaWR1YWxzJHNlZ21lbnRfbGVuZ3RoW2ldIDwtIChwb29sX3Jlc2lkdWFscyRkaXN0YW5jZVtpXSAtIHBvb2xfcmVzaWR1YWxzJGRpc3RhbmNlW2kgLSAxXSkgLyAyDQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgcG9vbF9yZXNpZHVhbHMkc2VnbWVudF9sZW5ndGhbaV0gPC0gDQogICAgICAgICAgICAoKHBvb2xfcmVzaWR1YWxzJGRpc3RhbmNlW2ldIC0gcG9vbF9yZXNpZHVhbHMkZGlzdGFuY2VbaSAtIDFdKSAvIDIpICsNCiAgICAgICAgICAgICgocG9vbF9yZXNpZHVhbHMkZGlzdGFuY2VbaSArIDFdIC0gcG9vbF9yZXNpZHVhbHMkZGlzdGFuY2VbaV0pIC8gMikNCiAgICAgICAgfQ0KICAgICAgfQ0KICAgICAgDQogICAgICAjIENhbGN1bGF0ZSB0aGUgbGVuZ3RoIG9mIHRoZSBwb29sDQogICAgICBwb29sX2xlbmd0aCA8LSBzdW0ocG9vbF9yZXNpZHVhbHMkc2VnbWVudF9sZW5ndGgsIG5hLnJtID0gVFJVRSkNCiAgICAgIA0KICAgICAgIyBDYWxjdWxhdGUgdGhlIHRvdGFsIGxlbmd0aCB3aXRoIEZpbmVzIGNvbnRhaW5pbmcgInkiIG9yICJ5ZXMiIChjYXNlLWluc2Vuc2l0aXZlKQ0KICAgICAgZmluZXNfbGVuZ3RoIDwtIHN1bSgNCiAgICAgICAgcG9vbF9yZXNpZHVhbHMkc2VnbWVudF9sZW5ndGhbDQogICAgICAgICAgZ3JlcGwoIlxcYih5fHllcylcXGIiLCBwb29sX3Jlc2lkdWFscyRGaW5lcywgaWdub3JlLmNhc2UgPSBUUlVFKQ0KICAgICAgICBdLA0KICAgICAgICBuYS5ybSA9IFRSVUUNCiAgICAgICkNCiAgICAgIA0KICAgICAgIyBDYWxjdWxhdGUgdGhlIHByb3BvcnRpb24NCiAgICAgIGZpbmVzX3Byb3BvcnRpb24gPC0gZmluZXNfbGVuZ3RoIC8gcG9vbF9sZW5ndGgNCiAgICAgIA0KICAgICAgIyBTdG9yZSByZXN1bHRzIGZvciB0aGUgY3VycmVudCBwb29sDQogICAgICBmaW5lc19wcm9wb3J0aW9uX3NpdGVfeWVhcltbYXMuY2hhcmFjdGVyKHBvb2xfaWQpXV0gPC0gbGlzdCgNCiAgICAgICAgcG9vbF9sZW5ndGggPSBwb29sX2xlbmd0aCwNCiAgICAgICAgZmluZXNfbGVuZ3RoID0gZmluZXNfbGVuZ3RoLA0KICAgICAgICBmaW5lc19wcm9wb3J0aW9uID0gZmluZXNfcHJvcG9ydGlvbg0KICAgICAgKQ0KICAgIH0NCiAgICANCiAgICAjIENvbnZlcnQgdGhlIHJlc3VsdHMgaW50byBhIGRhdGFmcmFtZSBmb3IgdGhlIGN1cnJlbnQgU2l0ZS95ZWFyDQogICAgaWYgKGxlbmd0aChmaW5lc19wcm9wb3J0aW9uX3NpdGVfeWVhcikgPiAwKSB7DQogICAgICBwb29sX2lkcyA8LSBuYW1lcyhmaW5lc19wcm9wb3J0aW9uX3NpdGVfeWVhcikNCiAgICAgIGZpbmVzX3Byb3BvcnRpb25fZGYgPC0gZGF0YS5mcmFtZSgNCiAgICAgICAgcG9vbF9pZCA9IHBvb2xfaWRzLA0KICAgICAgICBwb29sX2xlbmd0aCA9IHNhcHBseShmaW5lc19wcm9wb3J0aW9uX3NpdGVfeWVhciwgZnVuY3Rpb24oeCkgeCRwb29sX2xlbmd0aCksDQogICAgICAgIGZpbmVzX2xlbmd0aCA9IHNhcHBseShmaW5lc19wcm9wb3J0aW9uX3NpdGVfeWVhciwgZnVuY3Rpb24oeCkgeCRmaW5lc19sZW5ndGgpLA0KICAgICAgICBmaW5lc19wcm9wb3J0aW9uID0gc2FwcGx5KGZpbmVzX3Byb3BvcnRpb25fc2l0ZV95ZWFyLCBmdW5jdGlvbih4KSB4JGZpbmVzX3Byb3BvcnRpb24pLA0KICAgICAgICBTaXRlID0gc2l0ZSwNCiAgICAgICAgeWVhciA9IHllYXINCiAgICAgICkNCiAgICAgIA0KICAgICAgIyBDYWxjdWxhdGUgb3ZlcmFsbCBzdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIHRoZSBjdXJyZW50IFNpdGUveWVhcg0KICAgICAgdG90YWxfYWxsX3Bvb2xzX2xlbmd0aCA8LSBzdW0oZmluZXNfcHJvcG9ydGlvbl9kZiRwb29sX2xlbmd0aCwgbmEucm0gPSBUUlVFKQ0KICAgICAgdG90YWxfYWxsX2ZpbmVzX2xlbmd0aCA8LSBzdW0oZmluZXNfcHJvcG9ydGlvbl9kZiRmaW5lc19sZW5ndGgsIG5hLnJtID0gVFJVRSkNCiAgICAgIG92ZXJhbGxfZmluZXNfcHJvcG9ydGlvbiA8LSB0b3RhbF9hbGxfZmluZXNfbGVuZ3RoIC8gdG90YWxfYWxsX3Bvb2xzX2xlbmd0aA0KICAgICAgDQogICAgICAjIEFkZCB0aGUgb3ZlcmFsbCBzdW1tYXJ5IGFzIGEgZmluYWwgcm93DQogICAgICBmaW5hbF9yb3cgPC0gZGF0YS5mcmFtZSgNCiAgICAgICAgcG9vbF9pZCA9ICJUb3RhbCIsDQogICAgICAgIHBvb2xfbGVuZ3RoID0gdG90YWxfYWxsX3Bvb2xzX2xlbmd0aCwNCiAgICAgICAgZmluZXNfbGVuZ3RoID0gdG90YWxfYWxsX2ZpbmVzX2xlbmd0aCwNCiAgICAgICAgZmluZXNfcHJvcG9ydGlvbiA9IG92ZXJhbGxfZmluZXNfcHJvcG9ydGlvbiwNCiAgICAgICAgU2l0ZSA9IHNpdGUsDQogICAgICAgIHllYXIgPSB5ZWFyDQogICAgICApDQogICAgICANCiAgICAgICMgQmluZCB0aGUgZmluYWwgcm93IHRvIHRoZSBtYWluIGRhdGFmcmFtZQ0KICAgICAgZmluZXNfcHJvcG9ydGlvbl9kZiA8LSByYmluZChmaW5lc19wcm9wb3J0aW9uX2RmLCBmaW5hbF9yb3cpDQogICAgICANCiAgICAgICMgU3RvcmUgdGhlIHJlc3VsdCBmb3IgdGhlIGN1cnJlbnQgU2l0ZS95ZWFyDQogICAgICBmaW5lc19wcm9wb3J0aW9uX2xpc3RbW3Bhc3RlKHNpdGUsIHllYXIsIHNlcCA9ICJfIildXSA8LSBmaW5lc19wcm9wb3J0aW9uX2RmDQogICAgfQ0KICB9DQogIA0KICAjIENvbWJpbmUgcmVzdWx0cyBmcm9tIGFsbCBTaXRlcyBhbmQgeWVhcnMgaW50byBvbmUgZGF0YWZyYW1lDQogIGNvbWJpbmVkX2ZpbmVzX3Byb3BvcnRpb25fZGYgPC0gZG8uY2FsbChyYmluZCwgZmluZXNfcHJvcG9ydGlvbl9saXN0KQ0KICANCiAgcmV0dXJuKGNvbWJpbmVkX2ZpbmVzX3Byb3BvcnRpb25fZGYpDQp9DQpgYGANCg0KSG93ZXZlciwgc2hvdWxkIGl0IGJlIG9mIGdyZWF0ZXIgaW50ZXJlc3QgZm9yIHlvdXIgcHJvamVjdCwgd2UgaGF2ZSBpbmNsdWRlZCBpbiB0aGUgY29kZSBiZWxvdyB0aGUgYWJpbGl0eSB0byBzZWxlY3QgYSBzdWJzZXQgb2YgcG9vbHMuIENvbnNpc3RlbnQgd2l0aCB0aGUgcHJldmlvdXMgY3VzdG9tIGRlcHRoIHRocmVzaG9sZCwgeW91IGNhbiBhZGQgYSBzcGVjaWZpZWQgZGVwdGggaW4gbWV0cmVzLCBvciBlbnRlciAnTlVMTCcgdG8gc2VsZWN0IG9ubHkgcG9vbHMgd2l0aCBhIG1heGltdW0gcmVzaWR1YWwgZGVwdGggZ3JlYXRlciB0aGFuIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIHJlc2lkdWFsIGRlcHRocyBmb3IgdGhlIGVudGlyZSBzYW1wbGVkIHJlYWNoLiBPdXIgZGVmYXVsdCBpcyAwIChubyBzdWJzZXR0aW5nKS4NCg0KYGBge3IgZmluZXMgY3VzdG9tIGRlcHRofQ0KIyBEZWZpbmUgY3VzdG9tIHRocmVzaG9sZCBpZiByZXF1aXJlZC4gV2UgcmVjb21tZW5kIDAgKGFsbCByZXNpZHVhbCBwb29scywgcmVnYXJkbGVzcyBvZiBtYXhpbXVtIGRlcHRoKQ0KY3VzdG9tX2RlcHRoIDwtIDAgICMgUmVwbGFjZSB3aXRoIHlvdXIgZGVzaXJlZCB0aHJlc2hvbGQgaW4gbWV0cmVzLCBvciBzZXQgdG8gTlVMTCB0byB1c2UgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgcmVhY2ggKHRoYXQgeWVhcikNCmBgYA0KDQpgYGB7ciBmaW5lcyB0YWJsZSBkYXRhZnJhbWVzLCBlY2hvID0gRkFMU0V9DQojIENhbGwgdGhlIGNhbGN1bGF0ZV9maW5lc19wcm9wb3J0aW9uIGZ1bmN0aW9uIHdpdGggdGhlIHJlcXVpcmVkIHBhcmFtZXRlcnMNCmZpbmVzX3Byb3BvcnRpb25fcmVzdWx0IDwtIGNhbGN1bGF0ZV9maW5lc19wcm9wb3J0aW9uKA0KICBwb29sX2RhdGEgPSBwb29sX3N1bW1hcnlfcmVzdWx0LCAgICMgDQogIHJlc2lkdWFscy5kZiA9IHJlc2lkdWFscy5kZiwgICAgICAgIyANCiAgY3VzdG9tX2RlcHRoX3RocmVzaG9sZCA9IGN1c3RvbV9kZXB0aCwgICMgVXNlIGN1c3RvbSB0aHJlc2hvbGQgZm9yIGZpbHRlcmluZyAod2lsbCBvdmVyd3JpdGUgTlVMTCAvIFNEIGNhc2UpDQogIHVzZV9zZF90aHJlc2hvbGQgPSBUUlVFICAgICAgICAgICAgIyBUUlVFID0gU0QgaXMgdXNlZCB3aGVuIHRoZXJlIGlzIG5vIGN1c3RvbV9kZXB0aCBzcGVjaWZpZWQuIA0KKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiMgU3BsaXQgdGhlIHJlc3VsdHMgYnkgU2l0ZQ0Kc2l0ZV9zcGxpdCA8LSBzcGxpdChmaW5lc19wcm9wb3J0aW9uX3Jlc3VsdCwgZmluZXNfcHJvcG9ydGlvbl9yZXN1bHQkU2l0ZSkNCg0KIyBDcmVhdGUgYSBuYW1lZCBsaXN0IHRvIHN0b3JlIGVhY2ggc2l0ZSdzIGRhdGENCnNpdGVfZGF0YV9mcmFtZXMgPC0gbGlzdCgpDQoNCiMgTG9vcCB0aHJvdWdoIGVhY2ggc2l0ZSwgc29ydCB0aGUgZGF0YSwgYW5kIGRpc3BsYXkgdGhlIHRhYmxlcw0KZm9yIChzaXRlX25hbWUgaW4gbmFtZXMoc2l0ZV9zcGxpdCkpIHsNCiAgc2l0ZV9kYXRhIDwtIHNpdGVfc3BsaXRbW3NpdGVfbmFtZV1dDQogIA0KICAjIFNlcGFyYXRlIHRoZSAiVG90YWwiIHJvdw0KICB0b3RhbF9yb3cgPC0gc2l0ZV9kYXRhW3NpdGVfZGF0YSRwb29sX2lkID09ICJUb3RhbCIsIF0NCiAgc2l0ZV9kYXRhIDwtIHNpdGVfZGF0YVtzaXRlX2RhdGEkcG9vbF9pZCAhPSAiVG90YWwiLCBdDQogIA0KICAjIENvbnZlcnQgcG9vbF9pZCB0byBudW1lcmljIGZvciBzb3J0aW5nLCBoYW5kbGluZyBub24tbnVtZXJpYyB2YWx1ZXMNCiAgc2l0ZV9kYXRhJHBvb2xfaWRfbnVtZXJpYyA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihzaXRlX2RhdGEkcG9vbF9pZCkpDQogIA0KICAjIFNvcnQgYnkgeWVhciBhbmQgcG9vbF9pZF9udW1lcmljDQogIHNpdGVfZGF0YSA8LSBzaXRlX2RhdGFbb3JkZXIoc2l0ZV9kYXRhJHllYXIsIHNpdGVfZGF0YSRwb29sX2lkX251bWVyaWMpLCBdDQogIA0KICAjIERyb3AgdGhlIHRlbXBvcmFyeSBudW1lcmljIGNvbHVtbg0KICBzaXRlX2RhdGEkcG9vbF9pZF9udW1lcmljIDwtIE5VTEwNCiAgDQogICMgRW5zdXJlIHRoZSAiVG90YWwiIHJvdyBoYXMgdGhlIHNhbWUgY29sdW1ucyBhcyBzaXRlX2RhdGENCiAgdG90YWxfcm93IDwtIHRvdGFsX3Jvd1ssIG5hbWVzKHNpdGVfZGF0YSksIGRyb3AgPSBGQUxTRV0NCiAgDQogICMgUmVhdHRhY2ggdGhlICJUb3RhbCIgcm93IGF0IHRoZSBib3R0b20NCiAgc29ydGVkX3NpdGVfZGF0YSA8LSByYmluZChzaXRlX2RhdGEsIHRvdGFsX3JvdykNCiAgDQogICMgTW92ZSBTaXRlIGFuZCB5ZWFyIGNvbHVtbnMgdG8gdGhlIGxlZnQgYW5kIGZvcm1hdCB0aGUgZGF0YXRhYmxlDQogIHNvcnRlZF9zaXRlX2RhdGEgPC0gc29ydGVkX3NpdGVfZGF0YSAlPiUNCiAgICBzZWxlY3QoU2l0ZSwgeWVhciwgZXZlcnl0aGluZygpKSAgIyBNb3ZlIFNpdGUgYW5kIHllYXIgdG8gdGhlIGxlZnQNCiAgDQojIFJlbW92ZSByb3cgbmFtZXMgZnJvbSB0aGUgZGF0YSBmcmFtZSBleHBsaWNpdGx5DQogIHJvd25hbWVzKHNvcnRlZF9zaXRlX2RhdGEpIDwtIE5VTEwNCiAgDQogIyBTdG9yZSB0aGUgY2xlYW5lZCBkYXRhIGluIHRoZSBsaXN0DQogIHNpdGVfZGF0YV9mcmFtZXNbW3NpdGVfbmFtZV1dIDwtIHNvcnRlZF9zaXRlX2RhdGENCn0NCmBgYA0KDQpgYGB7ciBjcmVhdGUgdGFibGVzLCBlY2hvID0gRkFMU0UsIHJlc3VsdHM9J2FzaXMnfQ0KZm9yIChzaXRlX25hbWUgaW4gbmFtZXMoc2l0ZV9kYXRhX2ZyYW1lcykpIHsNCiAgIyBQcmVwYXJlIGdlbmVyaWMgZmlsZSBuYW1lIGZvciBleHBvcnQNCiAgZmlsZW5hbWUgPC0gcGFzdGUwKHNpdGVfbmFtZSwgIl9wb29sX2ZpbmVzLmNzdiIpICAjIC5jc3YgZXh0ZW5zaW9uDQogIA0KICAjIEV4cG9ydCB0aGUgdGFibGUgYXMgLmNzdg0KICBleHBvcnRfdGFibGUoc2l0ZV9kYXRhX2ZyYW1lc1tbc2l0ZV9uYW1lXV0sIGZpbGVuYW1lKQ0KICANCiAgI3ByaW50IHRhYmxlIGluIFINCiAgY2F0KCJcbiIpDQogIHByaW50KA0KICAgIGthYmxlKHNpdGVfZGF0YV9mcmFtZXNbW3NpdGVfbmFtZV1dLCANCiAgICAgICAgICBjYXB0aW9uID0gcGFzdGUoc2l0ZV9uYW1lLCAiLSBQb29sIEZpbmUgU2VkaW1lbnQiKSwgDQogICAgICAgICAgZm9ybWF0ID0gImh0bWwiLCBhbGlnbiA9ICJjIiwgZGlnaXRzID0gMykgJT4lDQogICAgICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRkFMU0UpDQogICkNCiAgY2F0KCJcbiIpDQp9DQoNCiMgRXhwb3J0IHRhYmxlIG9jY3VycyB3aXRoaW4gZnVuY3Rpb24gYWJvdmUNCmBgYA0KDQpUaGUgYWJvdmUgdGFibGVzIChhbHNvIGV4cG9ydGVkIHRvIG91dHB1dCBmb2xkZXIpIGluY2x1ZGUgYSBmaW5hbCByb3cgZm9yIGVhY2ggc2l0ZS15ZWFyIHdpdGggcmVhY2ggdG90YWwgcG9vbCBsZW5ndGgsIHJlYWNoIHRvdGFsIHBvb2wgbGVuZ3RoIHdpdGggZmluZSBzZWRpbWVudCwgYW5kIHRoZSByZWFjaHdpZGUgcHJvcG9ydGlvbiBvZiBwb29scyB3aXRoIGZpbmVzIChhIHJhdGlvIGZyb20gMCB0byAxKS4gQ29tcGFyaXNvbiBvZiB0aGUgcmVhY2h3aWRlIHByb3BvcnRpb24gYWxvbmUgbWF5IGJlIHN1ZmZpY2llbnQgdG8gZGVtb25zdHJhdGUgcHJvamVjdCBlZmZlY3RpdmVuZXNzLCBwZXJoYXBzIGNvbXBsZW1lbnRlZCB3aXRoIHRoZSBmaWd1cmUgdGhhdCB3ZSB3aWxsIGNyZWF0ZSBiZWxvdy4gSG93ZXZlciwgaWYgeW91IHdvdWxkIGxpa2UgdG8gc3RhdGlzdGljYWxseSBjb21wYXJlIGhvdyBmaW5lIHNlZGltZW50IGNoYW5nZWQgb3ZlciB0aW1lIGNvbXBhcmVkIHdpdGggYSBjb250cm9sLCB3ZSBjYW4gbG9vayBhdCB0aGUgZGlzdHJpYnV0aW9ucyBvZiB1bmRlcmx5aW5nIHBvb2wgZGF0YSAodGhlIGZpbmVzX3Byb3BvcnRpb24gZGF0YSBmb3IgZXZlcnkgcG9vbCkuDQoNCiMjIEluZmVyZW50aWFsIFRlc3RzIC0gRmluZXMNCg0KVGhpcyB0aW1lLCB3ZSBhcmUgZGVhbGluZyB3aXRoIGRhdGEgdGhhdCBhcmUgYm91bmRlZCBieSAwIGFuZCAxLiBBbmQgaW4gbWFueSBjYXNlcywgd2UgYWxzbyBhbnRpY2lwYXRlIGEgcmVsYXRpdmVseSBoaWdoIGZyZXF1ZW5jeSBvZiAwcyAobm8gZmluZXMgaW4gcG9vbHMpIGFuZC9vciAxcyAoZmluZXMgdGhyb3VnaG91dCkuIFdlIGFyZSBjb25maWRlbnQgdGhhdCBub24tdHJhbnNmb3JtZWQgZGF0YSB3b3VsZCB2aW9sYXRlIHRoZSBhc3N1bXB0aW9ucyBvZiBBTk9WQSwgc28gd2Ugb21pdCB0aGUgaW5pdGlhbCBkaWFnbm9zdGljIHRlc3RzLiBPdXIgYXR0ZW1wdHMgdG8gYXJjc2luZS10cmFuc2Zvcm0gdGhlIGRhdGEgd2VyZSBub3Qgc3VjY2Vzc2Z1bCwgYXMgb3VyIHRyYW5zZm9ybWVkIGRhdGEgcmVtYWluZWQgbm9uLW5vcm1hbGx5IGRpc3RyaWJ1dGVkIHdpdGggc2lnbmlmaWNhbnQgaGV0ZXJvc2NlZGFzdGljaXR5LiBBcyBzdWNoLCBhbmQgc2luY2Ugd2Ugc3VzcGVjdCBvdXIgZmluZXMgZGF0YSBkaXN0cmlidXRpb24gaXMgbm90IHBhcnRpY3VsYXJseSB1bnVzdWFsLCB3ZSBvcHRlZCBmb3IgQmV0YSByZWdyZXNzaW9uLg0KDQo8ZGl2IHN0eWxlPSJib3JkZXI6IDFweCBzb2xpZCAjZGRkOyBwYWRkaW5nOiAxMHB4OyBtYXJnaW46IDEwcHggMDsgYmFja2dyb3VuZC1jb2xvcjogI2Y5ZjlmOTsgZm9udC1zaXplOiBzbWFsbGVyOyI+DQpTbGlnaHRseSBuZXJkeSBiaXQsIGZlZWwgZnJlZSB0byBpZ25vcmU6IEJldGEgcmVncmVzc2lvbnMgYXJlIGNhcGFibGUgb2YgZGVhbGluZyB3aXRoIG5vbi1ub3JtYWwgaGV0ZXJvc2NlZGFzdGljIGRhdGEuIEFsdGhvdWdoIHRoZXkgY2Fubm90IGFjdHVhbGx5IGhhbmRsZSAwJ3MgYW5kIDEncywgZm9yIG91ciBjYXNlIHRoZXkgYXJlIHByZWZlcmFibGUgb3ZlciB0d28tcGFydCBtb2RlbHMgKGUuZy4gaHVyZGxlIG1vZGVscyk6IFNpbmNlIGFuIG9ic2VydmF0aW9uIG9mICJubyBmaW5lIHNlZGltZW50IiBjb3VsZCB2ZXJ5IHBsYXVzaWJseSBiZSByZWNvcmRlZCB3aGVyZSAyIGNtIG9mIGZpbmUgc2VkaW1lbnQgd2FzIGFjdHVhbGx5IHByZXNlbnQgaW4gYSAyMCBtIHBvb2wsIHdlIGFyZSBjb21mb3J0YWJsZSBhZGp1c3RpbmcgdGhlIDAncyBhbmQgMSdzIHRvIDAuMDAxIGFuZCAwLjk5OS4gV2UgZmVlbCBhIGh1cmRsZSBtb2RlbCB3b3VsZCBleGNlc3NpdmVseSBjb21wbGljYXRlIGludGVycHJldGFiaWxpdHkgKGUuZy4gYSBiaW5vbWlhbCBmaW5lcyBwcmVzZW5jZS9hYnNlbmNlIG1lY2hhbmlzbSBwbHVzIGEgZmluZXMgcXVhbnRpdHkgbWVjaGFuaXNtKS4gU2VlIEdlaXNzaW5nZXIgZXQgYWwgMjAyMiBpZiBpbnRlcmVzdGVkLg0KPC9kaXY+DQoNCldlIHdpbGwgZ2VuZXJhdGUgYSBmcmVxdWVuY3kgcGxvdCBvZiB0aGUgZmluZSBwcm9wb3J0aW9uIGRhdGEsIGZpdCB0aGUgQmV0YSByZWdyZXNzaW9uLCBhbmQgcGxvdCB0aGUgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbiBvZiB0aGUgcmVzaWR1YWxzICh3aGljaCBzaG91bGQgYmUgYnJvYWRseSBzeW1tZXRyaWNhbCBhcm91bmQgemVybykgYW5kIHRoZWlyIHJlbGF0aW9uc2hpcHMgdG8gdGhlIGZpdHRlZCB2YWx1ZXMgKGZvciB3aGljaCBubyBjbGVhciByZWxhdGlvbnNoaXAgb3IgaGV0ZXJvc2NlZGFzdGljaXR5IHNob3VsZCBiZSBldmlkZW50KS4gV2Ugd2lsbCBvbmx5IGV4cG9ydCB0aGUgcmVzdWx0cyBvZiB0aGUgQmV0YSByZWdyZXNzaW9uIHRvIHlvdXIgb3V0cHV0IGZvbGRlci4NCg0KYGBge3IgZmluZXMgZGF0YSBldmFsdWF0aW5nLCBlY2hvID0gRkFMU0V9DQojIyMjIGFkZCB0aGUgYmVmb3JlL2FmdGVyIGNhdGVnb3JpZXMgZnJvbSBwcmV2aW91cyBpbnB1dA0KZmluZXNfcHJvcG9ydGlvbl9yZXN1bHQgPC0gZmluZXNfcHJvcG9ydGlvbl9yZXN1bHQgJT4lDQogIG11dGF0ZShUaW1lX0NhdGVnb3J5ID0gY2FzZV93aGVuKA0KICAgIHllYXIgJWluJSBiZWZvcmVfeWVhcnMgfiAiQmVmb3JlIiwNCiAgICB5ZWFyICVpbiUgYWZ0ZXJfeWVhcnMgfiAiQWZ0ZXIiLA0KICAgIFRSVUUgfiBOQV9jaGFyYWN0ZXJfDQogICkpDQoNCiMgRmlsdGVyIG91dCBzaXRlcyB3aXRob3V0IGJvdGggdGltZSBjYXRlZ29yaWVzLiBSZW1vdmUgcm93cyB3aXRoIHBvb2xfaWQgPSAiVG90YWwiDQpmaW5lc19wcm9wb3J0aW9uX2ZpbHRlcmVkIDwtIGZpbmVzX3Byb3BvcnRpb25fcmVzdWx0ICU+JQ0KICBmaWx0ZXIocG9vbF9pZCAhPSAiVG90YWwiKSAlPiUNCiAgZ3JvdXBfYnkoU2l0ZSkgJT4lDQogIGZpbHRlcihhbGwoYygiQmVmb3JlIiwgIkFmdGVyIikgJWluJSBUaW1lX0NhdGVnb3J5KSkgJT4lDQogIHVuZ3JvdXAoKQ0KDQojIEFkanVzdCB2YWx1ZXMgb2YgZXhhY3RseSAwIG9yIDEgKGlmIGFueSkNCmZpbmVzX3Byb3BvcnRpb25fZmlsdGVyZWQgPC0gZmluZXNfcHJvcG9ydGlvbl9maWx0ZXJlZCAlPiUNCiAgbXV0YXRlKGZpbmVzX3Byb3BvcnRpb25fYWRqdXN0ZWQgPSBjYXNlX3doZW4oDQogICAgZmluZXNfcHJvcG9ydGlvbiA9PSAwIH4gMC4wMDEsICAjIFNsaWdodGx5IGFkanVzdCAwDQogICAgZmluZXNfcHJvcG9ydGlvbiA9PSAxIH4gMC45OTksICAjIFNsaWdodGx5IGFkanVzdCAxDQogICAgVFJVRSB+IGZpbmVzX3Byb3BvcnRpb24gICAgICAgICAjIEtlZXAgb3RoZXIgdmFsdWVzIGFzIGlzDQogICkpDQoNCiMgU3RlcCAyOiBWaXN1YWxpemUgdGhlIGRpc3RyaWJ1dGlvbiBvZiBmaW5lc19wcm9wb3J0aW9uDQpnZ3Bsb3QoZmluZXNfcHJvcG9ydGlvbl9maWx0ZXJlZCwgYWVzKHggPSBmaW5lc19wcm9wb3J0aW9uX2FkanVzdGVkKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMzAsIGZpbGwgPSAiYmx1ZSIsIGFscGhhID0gMC43KSArDQogIGdlb21fZGVuc2l0eShjb2xvciA9ICJyZWQiLCBsaW5ld2lkdGggPSAxKSArDQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIEZpbmVzIFByb3BvcnRpb24gKEFkanVzdGVkKSIsDQogICAgICAgeCA9ICJGaW5lcyBQcm9wb3J0aW9uIChBZGp1c3RlZCkiLCB5ID0gIkZyZXF1ZW5jeSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgU3RlcCAzOiBGaXQgYSBCZXRhIHJlZ3Jlc3Npb24gbW9kZWwNCiMgSW5jbHVkZSBTaXRlLCBZZWFyLCBhbmQgVGltZV9DYXRlZ29yeSBpbiB0aGUgZm9ybXVsYQ0KYmV0YV9tb2RlbCA8LSBiZXRhcmVnKGZpbmVzX3Byb3BvcnRpb25fYWRqdXN0ZWQgfiBTaXRlICogVGltZV9DYXRlZ29yeSwNCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZmluZXNfcHJvcG9ydGlvbl9maWx0ZXJlZCkNCg0KIyBTdGVwIDQ6IEFzc2VzcyBtb2RlbCBkaWFnbm9zdGljcw0KDQojIENoZWNrIHJlc2lkdWFscw0KZmluZXNfcHJvcG9ydGlvbl9maWx0ZXJlZCRyZXNpZHVhbHMgPC0gcmVzaWR1YWxzKGJldGFfbW9kZWwsIHR5cGUgPSAicGVhcnNvbiIpDQpnZ3Bsb3QoZmluZXNfcHJvcG9ydGlvbl9maWx0ZXJlZCwgYWVzKHggPSByZXNpZHVhbHMpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbnMgPSAzMCwgZmlsbCA9ICJibHVlIiwgYWxwaGEgPSAwLjcpICsNCiAgZ2VvbV9kZW5zaXR5KGNvbG9yID0gInJlZCIsIGxpbmV3aWR0aCA9IDEpICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgUmVzaWR1YWxzIiwgeCA9ICJSZXNpZHVhbHMiLCB5ID0gIkZyZXF1ZW5jeSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgUGxvdCBmaXR0ZWQgdnMgcmVzaWR1YWxzDQpmaW5lc19wcm9wb3J0aW9uX2ZpbHRlcmVkJGZpdHRlZCA8LSBmaXR0ZWQoYmV0YV9tb2RlbCkNCmdncGxvdChmaW5lc19wcm9wb3J0aW9uX2ZpbHRlcmVkLCBhZXMoeCA9IGZpdHRlZCwgeSA9IHJlc2lkdWFscykpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJyZWQiKSArDQogIGxhYnModGl0bGUgPSAiRml0dGVkIHZzIFJlc2lkdWFscyIsIHggPSAiRml0dGVkIFZhbHVlcyIsIHkgPSAiUmVzaWR1YWxzIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIyBTdW1tYXJ5IG9mIHRoZSBtb2RlbA0Kc3VtbWFyeShiZXRhX21vZGVsKQ0KDQojIEV4cG9ydCB0ZXN0IFN1bW1hcnkNCnN1bW1hcnlfdGV4dCA8LSBjYXB0dXJlLm91dHB1dChzdW1tYXJ5KGJldGFfbW9kZWwpKQ0KZXhwb3J0X3N1bW1hcnkoc3VtbWFyeV90ZXh0LCAiQmV0YSBSZWdyZXNzaW9uIG9mIEZpbmVzIGluIFBvb2xzIikNCmBgYA0KDQpTaW5jZSB5b3UgbWF5IG5vdCBiZSBmYW1pbGlhciB3aXRoIEJldGEgcmVncmVzc2lvbiwgaGVyZSBhcmUgc29tZSBiYXNpY3Mgb24gaW50ZXJwcmV0YXRpb24gZm9yIHRoZSB0ZXN0IG91dHB1dDoNCg0KLSAiT3B0aW1pemF0aW9uIGZhaWxlZCB0byBjb252ZXJnZS4uLiIgSWYgeW91IHNlZSB0aGlzIHdhcm5pbmcsIGl0IG1heSBiZSB0aGF0IHRoZXJlIHdlcmUgMCB2YWx1ZXMgYWNyb3NzIGFuIGVudGlyZSBTaXRlLiBUaGlzIHNob3VsZCBiZSBmYWlybHkgZWFzeSB0byBpbnRlcnByZXQgd2l0aG91dCBpbmZlcmVudGlhbCB0ZXN0cy4NCg0KLSBRdWFudGlsZSByZXNpZHVhbHMgbWVhc3VyZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBhY3R1YWwgZGF0YSBhbmQgcHJlZGljdGVkIHZhbHVlcy4gVGhlIG1lZGlhbiBzaG91bGQgYmUgY2xvc2UgdG8gMC4gQWxzbyBjaGVjayB0aGUgcmVzaWR1YWxzIHZzIGZpdHRlZCBwbG90IHRvIGVuc3VyZSB0aGVyZSBpcyBubyBjbGVhciB0cmVuZCBvciB1bnVzdWFsIG91dGxpZXJzDQoNCi0gQ29lZmZpY2llbnRzIChtZWFuIG1vZGVsKTogdGhlc2UgYXJlIHRoZSBlZmZlY3RzIG9mIHRoZSBwcmVkaWN0b3JzIChzaXRlLCB0aW1lKSBvbiB0aGUgcmVzcG9uc2UgdmFyaWFibGUgKGZpbmUgc2VkaW1lbnQgcHJvcG9ydGlvbiBpbiBwb29scykuICoqTG9vayBmb3Igc2lnbmlmaWNhbnQgcCB2YWx1ZXMgaW4gdGhlIGxhc3QgY29sdW1uLCBwYXJ0aWN1bGFybHkgZm9yIHRoZSBTaXRlXF9cX1xfXF9cX1w6VGltZVxfQ2F0ZWdvcnlcX1xfXF9cX1xfIHJvdywgd2hpY2ggaXMgdGhlIGludGVyYWN0aW9uIHRlcm0gKGlmIHNpZ25pZmljYW50LCB0aGlzIG1lYW5zIHRoZSBwcm9wb3J0aW9uIG9mIGZpbmVzIGluIHJlc2lkdWFsIHBvb2xzIGNoYW5nZWQgb3ZlciB0aW1lIGRpZmZlcmVudGx5IGJldHdlZW4gc2l0ZXMpKiouIA0KDQotIFBoaSBjb2VmZmljaWVudHM6IHRoZXJlIGlzIGEgcC12YWx1ZSBoZXJlIGFzIHdlbGwsIGJ1dCB0aGlzIHJlZmVycyB0byB3aGV0aGVyIHRoZSBzcHJlYWQgb2YgdGhlIGRhdGEgYXJvdW5kIHRoZSBtZWFuIHdhcyBhbiBpbXBvcnRhbnQgZmVhdHVyZS4gSWYgdGhlIHBoaSBlc3RpbWF0ZSBpcyB2ZXJ5IGhpZ2gsIHRoaXMgbWVhbnMgdGhlIGRhdGEgd2FzIGNvbmNlbnRyYXRlZCBhcm91bmQgdGhlIG1lYW4gKGZpbmVzIHByb3BvcnRpb24gZG9lc24ndCBmbHVjdHVhdGUgbXVjaCBiZXR3ZWVuIHNpdGVzL3RpbWVzKS4gQ29uc2lkZXIgcGhpIG9mIDAuMSB0byBiZSBzcHJlYWQgb3V0IGRhdGEsIDEgdG8gYmUgbW9kZXJhdGUsIGFuZCAxMCB0byBiZSBjb25jZW50cmF0ZWQgYXJvdW5kIHRoZSBtZWFuLg0KDQotIFBzZXVkbyBSLXNxdWFyZWQ6IHRoaXMgaXMgaG93IG11Y2ggb2YgdGhlIHZhcmlhdGlvbiBpbiBmaW5lcyBpbiBwb29scyBjYW4gYmUgZXhwbGFpbmVkIGJ5IHRoZSBzaXRlIGFuZCB0aW1lIHZhcmlhYmxlcy4gT2Z0ZW4gbG93IGluIGVjb2xvZ2ljYWwgY29udGV4dHMuDQoNClByb3BvcnRpb25hbCBkYXRhIGNhbiBiZSBsZXNzIGludHVpdGl2ZSB0byBpbnRlcnByZXQsIGFuZCB1c2luZyBhbiB1bmZhbWlsaWFyIGluZmVyZW50aWFsIHRlc3QgbWlnaHQgbm90IGNsZWFyIHRoaW5ncyB1cC4gTm90IHRvIHdvcnJ5OiBBZnRlciB3ZSBwZXJmb3JtIGEgc2ltaWxhciBhbmFseXNpcyB3aXRoIHRoZSBhcXVhdGljIHZlZ2V0YXRpb24gZGF0YSwgd2Ugd2lsbCBjcmVhdGUgc29tZSBwbG90cyB0aGF0IHNob3cgdGhlIGRpc3RyaWJ1dGlvbiBvZiBmaW5lcyBhbmQgYXF1YXRpY3MgYWNyb3NzIHRoZSByZWFjaC4gVGhlc2UgcGxvdHMgYXJlIG1vcmUgaW50dWl0aXZlIGFuZCB3aWxsIGhlbHAgeW91IHRvIGludGVycHJldCBhbnkgY2hhbmdlcyBpbiBncmVhdGVyIGNvbnRleHQuIA0KDQojIEFxdWF0aWMgVmVnZXRhdGlvbiBpbiBQb29scw0KDQpJbiB0aGUgZmllbGQsIHlvdSBtYXkgaGF2ZSBhbHNvIGVzdGltYXRlZCB0aGUgcHJvcG9ydGlvbiBvZiB0aGUgd2V0dGVkIHdpZHRoIHRoYXQgd2FzIG9jY3VwaWVkIGJ5IGFxdWF0aWMgdmVnZXRhdGlvbi4gRHVyaW5nIGRhdGEgd3JhbmdsaW5nIHdlIGFkZGVkIHRocmVlIG5ldyBkYXRhIGNvbHVtbnMgdG8gZmFjaWxpdGF0ZSBhbmFseXNlcyBvZiB0aGVzZSBhcXVhdGljIHZlZ2V0YXRpb24gb2JzZXJ2YXRpb25zOiBzdWJ2ZWcgKHN1Ym1lcmdlZCB2ZWdldGF0aW9uKSwgZmxvYXR2ZWcgKGZsb2F0aW5nIHZlZ2V0YXRpb24pLCBhbmQgZW1lcmd2ZWcgKGVtZXJnZW50IHZlZ2V0YXRpb24pLiBXZSB3aWxsIHVzZSB0aGVzZSB2YXJpYWJsZXMgdG8gZXN0aW1hdGUgdGhlIGxlbmd0aCBhbmQgcGxhbiBhcmVhIG9mIGVhY2ggcmVzaWR1YWwgcG9vbCB0aGF0IHdvdWxkIGJlIG9jY3VwaWVkIGJ5IGFxdWF0aWMgdmVnZXRhdGlvbiB3aGVuIGZsb3dzIGFwcHJvYWNoIHplcm8uIFRoZXNlIGNhbiBiZSB1c2VmdWwgbWV0cmljcyBmb3IgdHJhY2tpbmcgaGFiaXRhdCBxdWFsaXR5IGFuZCBtZWNoYW5pc21zIG9mIGhhYml0YXQgY2hhbmdlLCBob3dldmVyIHBsYW4gYXJlYSBlc3RpbWF0ZXMgY29tZSB3aXRoIGEgY2F2ZWF0Og0KDQo8c3BhbiBzdHlsZT0iZm9udC1zaXplOiBzbWFsbGVyOyBtYXJnaW4tbGVmdDogMjBweDsgZGlzcGxheTogYmxvY2s7Ij4NCkluIGVzdGltYXRpbmcgcGxhbiBhcmVhcyBvZiB2ZWdldGF0aW9uLCB3ZSBhc3N1bWUgdGhhdCB0aGUgcHJvcG9ydGlvbiBvZiByZXNpZHVhbCBwb29sIHdpZHRoIG9jY3VwaWVkIGJ5IHZlZ2V0YXRpb24gaXMgZXF1YWwgdG8gdGhlIHByb3BvcnRpb24gb2YgdGhlIHdldHRlZCB3aWR0aCB0aGF0IHdhcyBvY2N1cGllZCBpbiB0aGUgZmllbGQuIEluIG1vc3QgY2FzZXMgdGhpcyB3aWxsIGJlIGFuIG92ZXJlc3RpbWF0ZSBiZWNhdXNlIHRoZSB0aGFsd2VnIHdpbGwgdHlwaWNhbGx5IGhhdmUgbGVzcyB2ZWdldGF0aW9uIGFuZCwgYXMgZmxvd3MgcmVjZWRlLCB0aGUgdGhhbHdlZyBtYWtlcyB1cCBhIGdyZWF0ZXIgcHJvcG9ydGlvbiBvZiB0aGUgd2V0dGVkIHdpZHRoLiBBbHRob3VnaCB2ZWdldGF0ZWQgcmVzaWR1YWwgcG9vbCBhcmVhcyBjYW4gYmUgdXNlZnVsIGZvciB0cmFja2luZyBjaGFuZ2VzIG92ZXIgdGltZSwgYmVjYXVzZSB0aGV5IGFyZSBiYXNlZCBvbiBwcm9wb3J0aW9ucyBvZiB3ZXR0ZWQgd2lkdGhzLCB5b3Ugc2hvdWxkIG5vdCBjb25zaWRlciB0aGVtIGZsb3ctaW5kZXBlbmRlbnQuIFdoZW4gaW50ZXJwcmV0aW5nIGNoYW5nZXMgb3ZlciB0aW1lIChvciBmcm9tIGRpZmZlcmVudCByZWFjaGVzKSwgcmVtZW1iZXIgdGhhdCBpZiBmbG93cyB3ZXJlIG5vdGFibHkgZGlmZmVyZW50LCB0aGVuIHRoZSBhbW91bnQgb2Ygc3VibWVyZ2VkIHZlZ2V0YXRpb24gY2FuIGRpZmZlci4gSWYgeW91IGhhZCB0aGUgdGltZS9hYmlsaXR5IHRvIGNvbGxlY3Qgd2V0dGVkIHdpZHRoIG1lYXN1cmVtZW50cyBhdCBlYWNoIGludGVydmFsIHRoaXMgY291bGQgYmUgdXNlZCB0byBjb250cm9sIGZvciB0aGlzIHZhcmlhdGlvbiBieSBhZGRpbmcgaXQgYXMgYSBjb3ZhcmlhdGUgaW4gdGhlIGluZmVyZW50aWFsIHRlc3QuIE90aGVyd2lzZSwgaW50ZXJwcmV0IHdpdGggY2F1dGlvbi4NCjwvc3Bhbj4NCg0KQXNpZGUgZnJvbSB0aGUgYWJvdmUsIGluIHNvbWUgY2FzZXMgaXQgY2FuIGFsc28gYmUgZGlmZmljdWx0IHRvIGFzc2lnbiBwcm9wb3J0aW9ucyBjb25zaXN0ZW50bHkgaW4gdGhlIGZpZWxkLCBzdWNoIGFzIHdoZW4gaW52YXNpdmUgcmVlZCBjYW5hcnlncmFzIGZvcm1zIGRlbnNlIG1hdHMgdGhhdCBvYnNjdXJlIGJhbmtzIGFuZCB1bmRlcmx5aW5nIHNvaWxzL3N1YnN0cmF0ZXMuIElmIHRoZXJlIHdlcmUgc3VjaCBkaWZmaWN1bHRpZXMgaW4gdGhlIGZpZWxkLCB0aGVzZSBzaG91bGQgYmUgY2xlYXJseSBzdGF0ZWQgdG8gYWlkZSBpbnRlcnByZXRhdGlvbi4gRm9yIHRoZSBwdXJwb3NlcyBvZiBpbnRlcnByZXRhdGlvbiwgcmVtZW1iZXIgdGhhdCBpbiB0aGlzIHNlY3Rpb24gd2UgYXJlIGNvbnNpZGVyaW5nIHRoZSBwcm9wb3J0aW9ucyBvZiB0aGUgbGVuZ3RoIGFuZCB0aGUgYXJlYSBvZiAqcmVzaWR1YWwgcG9vbHMqIHRoYXQgYXJlIG9jY3VwaWVkIGJ5IGFxdWF0aWMgdmVnZXRhdGlvbi4gQXMgc3VjaCwgdGhlIGZpZWxkIG9ic2VydmF0aW9ucyBzaG91bGQgcmVsYXRlIHRvIHByb3BvcnRpb25zIG9mIHdldHRlZCB3aWR0aCAobm90IGJhbmtmdWxsKSwgYmVjYXVzZSBhdCBmbG93cyBhcHByb2FjaGluZyB6ZXJvIHRoZSB2ZWdldGF0aW9uIGJldHdlZW4gb2JzZXJ2ZWQgd2V0dGVkIHdpZHRoIGFuZCBiYW5rZnVsbCB3aWR0aCB3b3VsZCBub3Qgb2NjdXB5IGFueSBwYXJ0IG9mIHRoZSByZXNpZHVhbCBwb29sLiANCg0K8J+Mv/CfjL/wn4y/8J+Mv/CfjL8g8J+Mv/CfjL/wn4y/8J+Mv/CfjL8g8J+Mv/CfjL/wn4y/8J+Mv/CfjL8g8J+Mv/CfjL/wn4y/8J+Mv/CfjL8g8J+Mv/CfjL/wn4y/8J+Mv/CfjL8g8J+Mv/CfjL/wn4y/8J+Mv/CfjL8g8J+Mv/CfjL/wn4y/8J+Mv/CfjL8g8J+Mv/CfjL/wn4y/8J+Mv/CfjL8g8J+Mv/CfjL/wn4y/8J+Mv/CfjL8NCg0KYGBge3IgYXF1YXRpYyB2ZWcgaW4gcG9vbHMsIGVjaG8gPSBGQUxTRX0NCmNhbGN1bGF0ZV92ZWdfcHJvcG9ydGlvbiA8LSBmdW5jdGlvbihyZXNpZHVhbHMuZGYsIHZlZ19jb2x1bW4sIGN1c3RvbV9kZXB0aCA9IE5VTEwpIHsNCiAgIyBWYWxpZGF0ZSB0aGF0IHRoZSB2ZWdldGF0aW9uIGNvbHVtbiBleGlzdHMgaW4gdGhlIHJlc2lkdWFscyBkYXRhZnJhbWUNCiAgaWYgKCF2ZWdfY29sdW1uICVpbiUgY29sbmFtZXMocmVzaWR1YWxzLmRmKSkgew0KICAgIHN0b3AocGFzdGUoIlRoZSBjb2x1bW4iLCB2ZWdfY29sdW1uLCAiaXMgbm90IHByZXNlbnQgaW4gdGhlIHJlc2lkdWFscyBkYXRhZnJhbWUuIikpDQogIH0NCiAgDQogICMgSW5pdGlhbGl6ZSBhIGxpc3QgdG8gc3RvcmUgcmVzdWx0cw0KICB2ZWdfcHJvcG9ydGlvbl9saXN0IDwtIGxpc3QoKQ0KICANCiAgIyBJdGVyYXRlIG92ZXIgZWFjaCB1bmlxdWUgY29tYmluYXRpb24gb2YgU2l0ZSBhbmQgWWVhcg0KICB1bmlxdWVfc2l0ZXNfeWVhcnMgPC0gdW5pcXVlKHJlc2lkdWFscy5kZltjKCJTaXRlIiwgInllYXIiKV0pDQogIA0KZm9yIChpIGluIDE6bnJvdyh1bmlxdWVfc2l0ZXNfeWVhcnMpKSB7DQogIHNpdGUgPC0gdW5pcXVlX3NpdGVzX3llYXJzJFNpdGVbaV0NCiAgeWVhciA8LSB1bmlxdWVfc2l0ZXNfeWVhcnMkeWVhcltpXQ0KICANCiAgIyBTdWJzZXQgdGhlIHJlc2lkdWFscyBkYXRhZnJhbWUgZm9yIHRoZSBjdXJyZW50IFNpdGUgYW5kIFllYXINCiAgc3Vic2V0X3Jlc2lkdWFscyA8LSByZXNpZHVhbHMuZGZbcmVzaWR1YWxzLmRmJFNpdGUgPT0gc2l0ZSAmIHJlc2lkdWFscy5kZiR5ZWFyID09IHllYXIsIF0NCiAgDQogIGlmIChucm93KHN1YnNldF9yZXNpZHVhbHMpID09IDApIHsNCiAgICBtZXNzYWdlKHBhc3RlKCJObyBkYXRhIGZvciBTaXRlOiIsIHNpdGUsICJZZWFyOiIsIHllYXIsICItIHNraXBwaW5nLiIpKQ0KICAgIG5leHQNCiAgfQ0KICANCiAgIyBEZXRlcm1pbmUgdGhlIGRlcHRoIHRocmVzaG9sZCAoY3VzdG9tIG9yIFNEKQ0KICBkZXB0aF90aHJlc2hvbGQgPC0gaWYgKGlzLm51bGwoY3VzdG9tX2RlcHRoKSkgew0KICAgIHNkKHN1YnNldF9yZXNpZHVhbHMkcmVzaWR1YWxfZGVwdGgsIG5hLnJtID0gVFJVRSkNCiAgfSBlbHNlIHsNCiAgICBjdXN0b21fZGVwdGgNCiAgfQ0KICANCiAgIyBQcmludCB0aGUgZGVwdGggdGhyZXNob2xkDQogICNjYXQoIkRlcHRoIHRocmVzaG9sZCBmb3IgU2l0ZToiLCBzaXRlLCAiWWVhcjoiLCB5ZWFyLCAiaXM6IiwgZGVwdGhfdGhyZXNob2xkLCAiXG4iKQ0KICANCiAgICAjIEZpbHRlciBwb29scyBiYXNlZCBvbiBkZXB0aCB0aHJlc2hvbGQNCiAgICB2YWxpZF9wb29scyA8LSBzdWJzZXRfcmVzaWR1YWxzICU+JQ0KICAgICAgZ3JvdXBfYnkocG9vbF9pZCkgJT4lDQogICAgICBmaWx0ZXIobWF4KHJlc2lkdWFsX2RlcHRoLCBuYS5ybSA9IFRSVUUpID4gZGVwdGhfdGhyZXNob2xkKSAlPiUNCiAgICAgIHB1bGwocG9vbF9pZCkgJT4lDQogICAgICB1bmlxdWUoKQ0KICAgIA0KICAgICMgU3Vic2V0IHJlc2lkdWFscyBmb3IgdmFsaWQgcG9vbHMNCiAgICBzdWJzZXRfcmVzaWR1YWxzIDwtIHN1YnNldF9yZXNpZHVhbHNbc3Vic2V0X3Jlc2lkdWFscyRwb29sX2lkICVpbiUgdmFsaWRfcG9vbHMsIF0NCiAgICANCiAgICBpZiAobnJvdyhzdWJzZXRfcmVzaWR1YWxzKSA9PSAwKSB7DQogICAgICBtZXNzYWdlKHBhc3RlKCJObyB2YWxpZCBwb29scyBmb3IgU2l0ZToiLCBzaXRlLCAiWWVhcjoiLCB5ZWFyLCAiLSBza2lwcGluZy4iKSkNCiAgICAgIG5leHQNCiAgICB9DQogICAgDQogICAgIyBFbnN1cmUgdGhlIGRhdGFmcmFtZSBpcyBzb3J0ZWQgYnkgZGlzdGFuY2Ugd2l0aGluIGVhY2ggcG9vbA0KICAgIHN1YnNldF9yZXNpZHVhbHMgPC0gc3Vic2V0X3Jlc2lkdWFsc1tvcmRlcihzdWJzZXRfcmVzaWR1YWxzJHBvb2xfaWQsIHN1YnNldF9yZXNpZHVhbHMkZGlzdGFuY2UpLCBdDQogICAgDQojIEl0ZXJhdGUgb3ZlciBlYWNoIHVuaXF1ZSBwb29sX2lkDQp1bmlxdWVfcG9vbF9pZHMgPC0gdW5pcXVlKHN1YnNldF9yZXNpZHVhbHMkcG9vbF9pZCkNCmZvciAocG9vbF9pZCBpbiB1bmlxdWVfcG9vbF9pZHMpIHsNCiAgcG9vbF9yZXNpZHVhbHMgPC0gc3Vic2V0X3Jlc2lkdWFsc1tzdWJzZXRfcmVzaWR1YWxzJHBvb2xfaWQgPT0gcG9vbF9pZCwgXQ0KICANCiAgIyBJbml0aWFsaXplIHRoZSBzZWdtZW50X2xlbmd0aCBjb2x1bW4NCiAgcG9vbF9yZXNpZHVhbHMkc2VnbWVudF9sZW5ndGggPC0gTkENCiAgDQogICMgQ2FsY3VsYXRlIHNlZ21lbnQgbGVuZ3Rocw0KICBmb3IgKGkgaW4gMTpucm93KHBvb2xfcmVzaWR1YWxzKSkgew0KICAgIGlmIChpID09IDEpIHsNCiAgICAgICMgRmlyc3QgcG9pbnQ6IG9ubHkgaGFsZiB0aGUgZGlzdGFuY2UgdG8gdGhlIG5leHQgcG9pbnQNCiAgICAgIHBvb2xfcmVzaWR1YWxzJHNlZ21lbnRfbGVuZ3RoW2ldIDwtIChwb29sX3Jlc2lkdWFscyRkaXN0YW5jZVtpICsgMV0gLSBwb29sX3Jlc2lkdWFscyRkaXN0YW5jZVtpXSkgLyAyDQogICAgfSBlbHNlIGlmIChpID09IG5yb3cocG9vbF9yZXNpZHVhbHMpKSB7DQogICAgICAjIExhc3QgcG9pbnQ6IG9ubHkgaGFsZiB0aGUgZGlzdGFuY2UgdG8gdGhlIHByZXZpb3VzIHBvaW50DQogICAgICBwb29sX3Jlc2lkdWFscyRzZWdtZW50X2xlbmd0aFtpXSA8LSAocG9vbF9yZXNpZHVhbHMkZGlzdGFuY2VbaV0gLSBwb29sX3Jlc2lkdWFscyRkaXN0YW5jZVtpIC0gMV0pIC8gMg0KICAgIH0gZWxzZSB7DQogICAgICAjIE1pZGRsZSBwb2ludHM6IGhhbGYgdGhlIGRpc3RhbmNlIHRvIHRoZSBwcmV2aW91cyBhbmQgbmV4dCBwb2ludHMNCiAgICAgIHBvb2xfcmVzaWR1YWxzJHNlZ21lbnRfbGVuZ3RoW2ldIDwtIA0KICAgICAgICAoKHBvb2xfcmVzaWR1YWxzJGRpc3RhbmNlW2ldIC0gcG9vbF9yZXNpZHVhbHMkZGlzdGFuY2VbaSAtIDFdKSAvIDIpICsNCiAgICAgICAgKChwb29sX3Jlc2lkdWFscyRkaXN0YW5jZVtpICsgMV0gLSBwb29sX3Jlc2lkdWFscyRkaXN0YW5jZVtpXSkgLyAyKQ0KICAgIH0NCiAgfQ0KICANCiAgIyBQb29sIG1ldHJpY3MNCiAgcG9vbF9sZW5ndGggPC0gc3VtKHBvb2xfcmVzaWR1YWxzJHNlZ21lbnRfbGVuZ3RoLCBuYS5ybSA9IFRSVUUpDQogIHZlZ19sZW5ndGggPC0gc3VtKHBvb2xfcmVzaWR1YWxzJHNlZ21lbnRfbGVuZ3RoW3Bvb2xfcmVzaWR1YWxzW1t2ZWdfY29sdW1uXV0gPiAwXSwgbmEucm0gPSBUUlVFKQ0KICB2ZWdfcHJvcG9ydGlvbmFsX2xlbmd0aCA8LSB2ZWdfbGVuZ3RoIC8gcG9vbF9sZW5ndGgNCiAgdmVnX3Byb3BvcnRpb25hbF9hcmVhIDwtIHN1bShwb29sX3Jlc2lkdWFsc1tbdmVnX2NvbHVtbl1dICogcG9vbF9yZXNpZHVhbHMkc2VnbWVudF9sZW5ndGgsIG5hLnJtID0gVFJVRSkgLyBwb29sX2xlbmd0aCAjd2UgZG8gbm90IHVzZSByZXNpZHVhbCB3aWR0aHMgaGVyZSwgd2hpY2ggY291bGQgY29tcGxpY2F0ZSBpbnRlcnByZXRhdGlvbiAoZS5nLiwgYXJlYXMgb2Ygd2V0dGVkIHZlZ2V0YXRpb24gZ3JlYXRlciB0aGFuIHRoZSB3ZXR0ZWQgYXJlYSkgd2l0aG91dCBhbnkgYmVuZWZpdCB0aGF0IHdlIGFyZSBhd2FyZSBvZi4NCg0KICAjIFN0b3JlIHJlc3VsdHMNCiAgdmVnX3Byb3BvcnRpb25fbGlzdFtbcGFzdGUoc2l0ZSwgeWVhciwgcG9vbF9pZCwgc2VwID0gIl8iKV1dIDwtIGxpc3QoDQogICAgc2l0ZSA9IHNpdGUsDQogICAgeWVhciA9IHllYXIsDQogICAgcG9vbF9pZCA9IHBvb2xfaWQsDQogICAgcG9vbF9sZW5ndGggPSBwb29sX2xlbmd0aCwNCiAgICB2ZWdfbGVuZ3RoID0gdmVnX2xlbmd0aCwNCiAgICB2ZWdfcHJvcG9ydGlvbmFsX2xlbmd0aCA9IHZlZ19wcm9wb3J0aW9uYWxfbGVuZ3RoLA0KICAgIHZlZ19wcm9wb3J0aW9uYWxfYXJlYSA9IHZlZ19wcm9wb3J0aW9uYWxfYXJlYQ0KICApDQp9DQoNCiAgICAjIFNpdGUtWWVhciBUb3RhbHMNCiAgICB0b3RhbF9wb29sX2xlbmd0aCA8LSBzdW0oc2FwcGx5KHZlZ19wcm9wb3J0aW9uX2xpc3QsIGZ1bmN0aW9uKHgpIGlmICh4JHNpdGUgPT0gc2l0ZSAmJiB4JHllYXIgPT0geWVhcikgeCRwb29sX2xlbmd0aCBlbHNlIDApLCBuYS5ybSA9IFRSVUUpDQogICAgdG90YWxfdmVnX2xlbmd0aCA8LSBzdW0oc2FwcGx5KHZlZ19wcm9wb3J0aW9uX2xpc3QsIGZ1bmN0aW9uKHgpIGlmICh4JHNpdGUgPT0gc2l0ZSAmJiB4JHllYXIgPT0geWVhcikgeCR2ZWdfbGVuZ3RoIGVsc2UgMCksIG5hLnJtID0gVFJVRSkNCiAgICB0b3RhbF92ZWdfcHJvcG9ydGlvbmFsX2xlbmd0aCA8LSB0b3RhbF92ZWdfbGVuZ3RoIC8gdG90YWxfcG9vbF9sZW5ndGgNCiAgICB0b3RhbF92ZWdfcHJvcG9ydGlvbmFsX2FyZWEgPC0gc3VtKHNhcHBseSh2ZWdfcHJvcG9ydGlvbl9saXN0LCBmdW5jdGlvbih4KSBpZiAoeCRzaXRlID09IHNpdGUgJiYgeCR5ZWFyID09IHllYXIpIHgkdmVnX3Byb3BvcnRpb25hbF9hcmVhICogeCRwb29sX2xlbmd0aCBlbHNlIDApLCBuYS5ybSA9IFRSVUUpIC8gdG90YWxfcG9vbF9sZW5ndGgNCiAgICANCiAgICB2ZWdfcHJvcG9ydGlvbl9saXN0W1twYXN0ZShzaXRlLCB5ZWFyLCAiVG90YWwiLCBzZXAgPSAiXyIpXV0gPC0gbGlzdCgNCiAgICAgIHNpdGUgPSBzaXRlLA0KICAgICAgeWVhciA9IHllYXIsDQogICAgICBwb29sX2lkID0gIlRvdGFsIiwNCiAgICAgIHBvb2xfbGVuZ3RoID0gdG90YWxfcG9vbF9sZW5ndGgsDQogICAgICB2ZWdfbGVuZ3RoID0gdG90YWxfdmVnX2xlbmd0aCwNCiAgICAgIHZlZ19wcm9wb3J0aW9uYWxfbGVuZ3RoID0gdG90YWxfdmVnX3Byb3BvcnRpb25hbF9sZW5ndGgsDQogICAgICB2ZWdfcHJvcG9ydGlvbmFsX2FyZWEgPSB0b3RhbF92ZWdfcHJvcG9ydGlvbmFsX2FyZWENCiAgICApDQogIH0NCiAgDQogICMgQ29tYmluZSBpbnRvIGEgZGF0YWZyYW1lDQogIHZlZ19wcm9wb3J0aW9uX2RmIDwtIGRvLmNhbGwocmJpbmQsIGxhcHBseSh2ZWdfcHJvcG9ydGlvbl9saXN0LCBmdW5jdGlvbih4KSB7DQogICAgZGF0YS5mcmFtZSgNCiAgICAgIHNpdGUgPSB4JHNpdGUsDQogICAgICB5ZWFyID0geCR5ZWFyLA0KICAgICAgcG9vbF9pZCA9IHgkcG9vbF9pZCwNCiAgICAgIHBvb2xfbGVuZ3RoID0geCRwb29sX2xlbmd0aCwNCiAgICAgIHZlZ19sZW5ndGggPSB4JHZlZ19sZW5ndGgsDQogICAgICB2ZWdfcHJvcG9ydGlvbmFsX2xlbmd0aCA9IHgkdmVnX3Byb3BvcnRpb25hbF9sZW5ndGgsDQogICAgICB2ZWdfcHJvcG9ydGlvbmFsX2FyZWEgPSB4JHZlZ19wcm9wb3J0aW9uYWxfYXJlYQ0KICAgICkNCiAgfSkpDQogIA0KICByZXR1cm4odmVnX3Byb3BvcnRpb25fZGYpDQp9DQpgYGANClRoZSB0YWJsZXMgZ2VuZXJhdGVkIGFuZCBleHBvcnRlZCBieSB0aGUgY29kZSBiZWxvdyB3aWxsIHNob3cgdGhlIHByb3BvcnRpb25hbCBsZW5ndGggb2YgcmVzaWR1YWwgcG9vbHMgaW4gd2hpY2ggYXF1YXRpYyB2ZWdldGF0aW9uIHdhcyBwcmVzZW50IChyZWdhcmRsZXNzIG9mIHF1YW50aXR5L3dpZHRoKSwgaW4gdGhlIHNhbWUgd2F5IHRoYXQgd2UgdXNlZCB0aGUgZmluZXMgZGF0YS4gVGhlIHRhYmxlcyBhbHNvIHNob3cgdGhlIHBsYW4gYXJlYSBvZiByZXNpZHVhbCBwb29scyB0aGF0IGZlYXR1cmVkIGFxdWF0aWMgdmVnZXRhdGlvbiwgYmFzZWQgb24geW91ciBlc3RpbWF0ZXMgb2YgdGhlIHByb3BvcnRpb24gb2Ygd2V0dGVkIHdpZHRoIG9jY3VwaWVkIGJ5IHZlZ2V0YXRpb24gYXQgZWFjaCBpbnRlcnZhbCwgaW50ZWdyYXRlZCBhbG9uZyB0aGUgbGVuZ3RoIG9mIGVhY2ggcG9vbC4NCg0KSnVzdCBsaWtlIGZvciBmaW5lcywgZm9yIGFxdWF0aWMgdmVnZXRhdGlvbiB3ZSBkZWZhdWx0IHRvIHVzaW5nIHRoZSBmdWxsIGNvbnRpbmdlbnQgb2YgcG9vbHMuIE91ciByYXRpb25hbGUgaXMgdGhhdCB2ZWdldGF0aW9uIChwYXJ0aWN1bGFybHkgY2VydGFpbiBwcm9ibGVtYXRpYyBpbnZhc2l2ZSBzcGVjaWVzKSBjYW4gYmUgaW52b2x2ZWQgaW4gdGhlIHByb2Nlc3Mgb2YgaW5maWxsaW5nIHBvb2xzIGJ5IHRyYXBwaW5nIHNlZGltZW50LCBhbmQgaXQgbWF5IGJlIG9mIHJlc3RvcmF0aW9uIHNpZ25pZmljYW5jZSB0byB0cmFjayBjaGFuZ2VzIGluIHZlZ2V0YXRpb24gaW4gbWlub3IgbmFzY2VudCBvciBpbmZpbGxpbmcgcG9vbHMuIEhvd2V2ZXIsIGFzIGJlZm9yZSwgd2UgaGF2ZSBpbmNsdWRlZCBpbiB0aGUgY29kZSBiZWxvdyB0aGUgYWJpbGl0eSB0byBzZWxlY3QgYSBzdWJzZXQgb2YgcG9vbHMsIGZvciBleGFtcGxlIGlmIHlvdSB3YW50IHRvIGZvY3VzIG9uIGZhY3RvcnMgc3VjaCBhcyB0aGUgaW1wb3J0YW5jZSBvZiBhcXVhdGljIHZlZ2V0YXRpdmUgY292ZXIgdGhhdCB3b3VsZCBwbGF1c2libHkgYmUgdXNlZCBieSByZWFyaW5nIGZpc2ggaW4gc3VtbWVyIChpLmUuLCBvbmx5IGluIHBvb2xzIG9mIGEgY2VydGFpbiBkZXB0aCkuIE91ciBkZWZhdWx0IGlzIDAgKG5vIHN1YnNldHRpbmcpLCBhbmQgaWYgeW91IGNoYW5nZSBpdCwgZW5zdXJlIHRoYXQgd2hlbiBjb21wYXJpbmcgc3lzdGVtcyBvciB5ZWFycyB5b3UgYXJlIGNvbXBhcmluZyBsaWtlIGZvciBsaWtlLg0KDQpgYGB7ciBBcXVhdGljIHZlZyBjdXN0b20gdGhyZXNob2xkfQ0KIyBEZWZpbmUgY3VzdG9tIHRocmVzaG9sZCBpZiByZXF1aXJlZC4gV2UgcmVjb21tZW5kIDAgKGFsbCByZXNpZHVhbCBwb29scywgcmVnYXJkbGVzcyBvZiBtYXhpbXVtIGRlcHRoKQ0KY3VzdG9tX2RlcHRoIDwtIDAgICMgUmVwbGFjZSB3aXRoIHlvdXIgZGVzaXJlZCB0aHJlc2hvbGQgaW4gbWV0cmVzLCBvciBzZXQgdG8gTlVMTCB0byB1c2UgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgcmVhY2ggKHRoYXQgeWVhcikNCmBgYA0KDQpgYGB7ciBBcXVhdGljIHZlZyB0YWJsZXMsIGVjaG8gPSBGQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMgQ2FsbCB0aGUgZnVuY3Rpb24gd2l0aCB0aGUgY3VzdG9tIGRlcHRoIHRocmVzaG9sZA0Kc3VidmVnX3Jlc3VsdCA8LSBjYWxjdWxhdGVfdmVnX3Byb3BvcnRpb24ocmVzaWR1YWxzLmRmLCB2ZWdfY29sdW1uID0gInN1YnZlZyIsIGN1c3RvbV9kZXB0aCA9IGN1c3RvbV9kZXB0aCkNCmVtZXJndmVnX3Jlc3VsdCA8LSBjYWxjdWxhdGVfdmVnX3Byb3BvcnRpb24ocmVzaWR1YWxzLmRmLCB2ZWdfY29sdW1uID0gImVtZXJndmVnIiwgY3VzdG9tX2RlcHRoID0gY3VzdG9tX2RlcHRoKQ0KZmxvYXR2ZWdfcmVzdWx0IDwtIGNhbGN1bGF0ZV92ZWdfcHJvcG9ydGlvbihyZXNpZHVhbHMuZGYsIHZlZ19jb2x1bW4gPSAiZmxvYXR2ZWciLCBjdXN0b21fZGVwdGggPSBjdXN0b21fZGVwdGgpDQoNCiMgRXh0cmFjdCAiVG90YWwiIHJvd3MgZm9yIGVhY2ggdGFibGUNCnN1YnZlZ190b3RhbCA8LSBzdWJ2ZWdfcmVzdWx0W3N1YnZlZ19yZXN1bHQkcG9vbF9pZCA9PSAiVG90YWwiLCBdDQplbWVyZ3ZlZ190b3RhbCA8LSBlbWVyZ3ZlZ19yZXN1bHRbZW1lcmd2ZWdfcmVzdWx0JHBvb2xfaWQgPT0gIlRvdGFsIiwgXQ0KZmxvYXR2ZWdfdG90YWwgPC0gZmxvYXR2ZWdfcmVzdWx0W2Zsb2F0dmVnX3Jlc3VsdCRwb29sX2lkID09ICJUb3RhbCIsIF0NCg0KIyBFeHBvcnQgdGhlICJUb3RhbCIgcm93cyBmb3IgZWFjaCB2ZWdldGF0aW9uIHR5cGUgYXMgQ1NWIGZpbGVzDQpleHBvcnRfdGFibGUoc3VidmVnX3RvdGFsLCAiUmVhY2h3aWRlIFN1Ym1lcmdlZCBWZWcuY3N2IikgI2NhbiBhbHRlciB0aGVzZSB0byBzdWJ2ZWdfcmVzdWx0IChldGMuKSBpZiBmdWxsIGRhdGEgcmVxdWlyZWQNCmV4cG9ydF90YWJsZShlbWVyZ3ZlZ190b3RhbCwgIlJlYWNod2lkZSBFbWVyZ2VudCBWZWcuY3N2IikNCmV4cG9ydF90YWJsZShmbG9hdHZlZ190b3RhbCwgIlJlYWNod2lkZSBGbG9hdGluZyBWZWcuY3N2IikNCg0KIyBQcmludCB0YWJsZXMgZm9yIHZpc3VhbGl6YXRpb24gaW4gUlN0dWRpbyAvIGtuaXQNCmthYmxlKHN1YnZlZ190b3RhbCwgY2FwdGlvbiA9ICJSZWFjaHdpZGUgU3VibWVyZ2VkIFZlZ2V0YXRpb24gZm9yIEVhY2ggU2l0ZS1ZZWFyIikNCmthYmxlKGVtZXJndmVnX3RvdGFsLCBjYXB0aW9uID0gIlJlYWNod2lkZSBFbWVyZ2VudCBWZWdldGF0aW9uIGZvciBFYWNoIFNpdGUtWWVhciIpDQprYWJsZShmbG9hdHZlZ190b3RhbCwgY2FwdGlvbiA9ICJSZWFjaHdpZGUgRmxvYXRpbmcgVmVnZXRhdGlvbiBmb3IgRWFjaCBTaXRlLVllYXIiKQ0KYGBgDQoNCiMjIEluZmVyZW50aWFsIFRlc3RzIC0gQXF1YXRpYyBWZWcNCg0KSnVzdCBsaWtlIHdpdGggdGhlIGZpbmVzIGRhdGEsIHdlIGFyZSBkZWFsaW5nIHdpdGggZGF0YSB0aGF0IGFyZSBib3VuZGVkIGJ5IDAgYW5kIDEgKGZvciBib3RoIHByb3BvcnRpb25zIG9mIGxlbmd0aCBhbmQgZm9yIGFyZWEsIGFjcm9zcyBlYWNoIHR5cGUgb2YgdmVnZXRhdGlvbikuIFRoZSBub24tdHJhbnNmb3JtZWQgZGF0YSB3b3VsZCBiZSBleHBlY3RlZCB0byB2aW9sYXRlIHRoZSBhc3N1bXB0aW9ucyBvZiBBTk9WQSwgc28gd2Ugb21pdCB0aGUgaW5pdGlhbCBkaWFnbm9zdGljIHRlc3RzLiBXZSB3aWxsIGFnYWluIGFwcGx5IEJldGEgcmVncmVzc2lvbnMuDQoNCkJlbG93IHdlIGRpc3BsYXkgdGhlIEJldGEgcmVncmVzc2lvbiBtb2RlbCBzdW1tYXJpZXMgZm9yIGFsbCB2ZWdldGF0aW9uIGNhdGVnb3JpZXMgKHdoZXJlIHByZXNlbnQpLCBib3RoIGxlbmd0aCBhbmQgYXJlYSBwcm9wb3J0aW9ucy4gV2Ugb21pdCB0aGUgZGlhZ25vc3RpYyBwbG90cyBmcm9tIHRoZSBkaXNwbGF5LCBidXQgd2hlbiB5b3UgcnVuIHRoZSBjb2RlIGZvciB5b3VyIGRhdGEsIHlvdSBzaG91bGQgZXhhbWluZSB0aGUgcGxvdHMuDQoNCmBgYHtyIGFxdWF0aWMgdmVnIGluZmVyZW50aWFscywgZWNobyA9IEZBTFNFfQ0KIyBGdW5jdGlvbiB0byBydW4gQmV0YSByZWdyZXNzaW9uIGFuZCBkaWFnbm9zdGljcw0KcnVuX2JldGFfcmVncmVzc2lvbiA8LSBmdW5jdGlvbihkYXRhLCByZXNwb25zZV92YXIsIGRhdGFzZXRfbmFtZSwgc3VtbWFyeV9saXN0KSB7DQogICMgQ3JlYXRlIHRoZSBUaW1lX0NhdGVnb3J5DQogIGRhdGEgPC0gZGF0YSAlPiUNCiAgICBtdXRhdGUoVGltZV9DYXRlZ29yeSA9IGNhc2Vfd2hlbigNCiAgICAgIHllYXIgJWluJSBiZWZvcmVfeWVhcnMgfiAiQmVmb3JlIiwNCiAgICAgIHllYXIgJWluJSBhZnRlcl95ZWFycyB+ICJBZnRlciIsDQogICAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXw0KICAgICkpDQoNCiAgIyBGaWx0ZXIgc2l0ZXMgd2l0aCBib3RoIHRpbWUgY2F0ZWdvcmllcyBhbmQgcmVtb3ZlICJUb3RhbCINCiAgZmlsdGVyZWRfZGF0YSA8LSBkYXRhICU+JQ0KICAgIGZpbHRlcihwb29sX2lkICE9ICJUb3RhbCIpICU+JQ0KICAgIGdyb3VwX2J5KHNpdGUpICU+JQ0KICAgIGZpbHRlcihhbGwoYygiQmVmb3JlIiwgIkFmdGVyIikgJWluJSBUaW1lX0NhdGVnb3J5KSkgJT4lDQogICAgdW5ncm91cCgpDQoNCiAgIyBBZGp1c3QgcmVzcG9uc2UgdmFyaWFibGUgdmFsdWVzIG9mIGV4YWN0bHkgMCBvciAxDQogIGZpbHRlcmVkX2RhdGEgPC0gZmlsdGVyZWRfZGF0YSAlPiUNCiAgICBtdXRhdGUocmVzcG9uc2VfYWRqdXN0ZWQgPSBjYXNlX3doZW4oDQogICAgICAhIXN5bShyZXNwb25zZV92YXIpID09IDAgfiAwLjAwMSwNCiAgICAgICEhc3ltKHJlc3BvbnNlX3ZhcikgPT0gMSB+IDAuOTk5LA0KICAgICAgVFJVRSB+ICEhc3ltKHJlc3BvbnNlX3ZhcikNCiAgICApKQ0KDQogICMgRml0IEJldGEgcmVncmVzc2lvbiBtb2RlbA0KICBiZXRhX21vZGVsIDwtIHRyeUNhdGNoKA0KICAgIGJldGFyZWcocmVzcG9uc2VfYWRqdXN0ZWQgfiBzaXRlICogVGltZV9DYXRlZ29yeSwgZGF0YSA9IGZpbHRlcmVkX2RhdGEpLA0KICAgIHdhcm5pbmcgPSBmdW5jdGlvbih3KSB7DQogICAgICB3YXJuaW5nX21lc3NhZ2UgPC0gcGFzdGUoIlxuV2FybmluZzogb3B0aW1pemF0aW9uIGZhaWxlZCB0byBjb252ZXJnZSBmb3IiLCByZXNwb25zZV92YXIsICJpbiIsIGRhdGFzZXRfbmFtZSwgImRhdGFzZXRcbiIpDQogICAgICBjYXQod2FybmluZ19tZXNzYWdlKSAgIyBEaXNwbGF5IHRoZSB3YXJuaW5nIG1lc3NhZ2UNCiAgICAgIHJldHVybihOVUxMKQ0KICAgIH0NCiAgKQ0KDQogIGlmICghaXMubnVsbChiZXRhX21vZGVsKSkgew0KICAgICMgSWYgbW9kZWwgY29udmVyZ2VzLCBjYXB0dXJlIHRoZSBzdW1tYXJ5IGFuZCBkaXNwbGF5IGl0DQogICAgbW9kZWxfc3VtbWFyeSA8LSBjYXB0dXJlLm91dHB1dChzdW1tYXJ5KGJldGFfbW9kZWwpKQ0KICAgIA0KICAgICMgQXBwZW5kIHRoZSBzdW1tYXJ5IHRvIHRoZSBsaXN0DQogICAgc3VtbWFyeV9saXN0IDwtIGMoc3VtbWFyeV9saXN0LCBwYXN0ZSgiU3RhcnQgb2Ygc3VtbWFyeSBmb3IiLCByZXNwb25zZV92YXIsICJpbiIsIGRhdGFzZXRfbmFtZSwgImRhdGFzZXQiKSwgbW9kZWxfc3VtbWFyeSwgcGFzdGUoIlxuXG5cbiIpKQ0KICAgIA0KICAgICMgUHJpbnQgdGhlIG1vZGVsIHN1bW1hcnkgdG8gdGhlIGNvbnNvbGUNCiAgICBjYXQoIlxuXG5cbk1vZGVsIFN1bW1hcnkgZm9yIiwgcmVzcG9uc2VfdmFyLCAiaW4iLCBkYXRhc2V0X25hbWUsICJkYXRhc2V0OlxuIikNCiAgICBwcmludChzdW1tYXJ5KGJldGFfbW9kZWwpKQ0KICB9IGVsc2Ugew0KICAgICMgSWYgbW9kZWwgZG9lcyBub3QgY29udmVyZ2UsIGp1c3QgcHJpbnQgYSBtZXNzYWdlDQogICAgY2F0KCJcblxuXG5ObyBtb2RlbCBjb252ZXJnZW5jZSBmb3IiLCByZXNwb25zZV92YXIsICJpbiIsIGRhdGFzZXRfbmFtZSwgIlxuIikNCiAgfQ0KDQogIHJldHVybihzdW1tYXJ5X2xpc3QpDQp9DQoNCiMgRGVmaW5lIGRhdGFzZXRzIGFuZCByZXNwb25zZSB2YXJpYWJsZXMNCmRhdGFzZXRzIDwtIGxpc3Qoc3VidmVnX3Jlc3VsdCA9IHN1YnZlZ19yZXN1bHQsIA0KICAgICAgICAgICAgICAgICBlbWVyZ3ZlZ19yZXN1bHQgPSBlbWVyZ3ZlZ19yZXN1bHQsIA0KICAgICAgICAgICAgICAgICBmbG9hdHZlZ19yZXN1bHQgPSBmbG9hdHZlZ19yZXN1bHQpDQpyZXNwb25zZV92YXJzIDwtIGMoInZlZ19wcm9wb3J0aW9uYWxfbGVuZ3RoIiwgInZlZ19wcm9wb3J0aW9uYWxfYXJlYSIpDQoNCiMgSW5pdGlhbGl6ZSBhbiBlbXB0eSBsaXN0IHRvIHN0b3JlIGFsbCBzdW1tYXJpZXMNCmFsbF9zdW1tYXJpZXMgPC0gY2hhcmFjdGVyKCkNCg0KIyBSdW4gdGhlIGZ1bmN0aW9uIGZvciBlYWNoIGNvbWJpbmF0aW9uIG9mIGRhdGFzZXQgYW5kIHJlc3BvbnNlIHZhcmlhYmxlDQpmb3IgKGRhdGFzZXRfbmFtZSBpbiBuYW1lcyhkYXRhc2V0cykpIHsNCiAgZm9yIChyZXNwb25zZV92YXIgaW4gcmVzcG9uc2VfdmFycykgew0KICAgIGFsbF9zdW1tYXJpZXMgPC0gcnVuX2JldGFfcmVncmVzc2lvbihkYXRhc2V0c1tbZGF0YXNldF9uYW1lXV0sIHJlc3BvbnNlX3ZhciwgZGF0YXNldF9uYW1lLCBhbGxfc3VtbWFyaWVzKQ0KICB9DQp9DQoNCiMgRXhwb3J0IGFsbCBzdW1tYXJpZXMgYXMgYSBzaW5nbGUgLnR4dCBmaWxlLiBTdW1tYXJpZXMgZ2VuZXJhdGVkIHdpdGhpbiBmdW5jdGlvbg0KZXhwb3J0X3N1bW1hcnkoYWxsX3N1bW1hcmllcywgIkFxdWF0aWMgVmVnZXRhdGlvbiBCZXRhIFJlZ3Jlc3Npb25zIikNCmBgYA0KDQpgYGB7ciBhcXVhdGljIHZlZyBkaWFnbm9zdGljIHBsb3RzLCBpbmNsdWRlPUZBTFNFfQ0KZm9yIChkYXRhc2V0X25hbWUgaW4gbmFtZXMoZGF0YXNldHMpKSB7DQogIGZvciAocmVzcG9uc2VfdmFyIGluIHJlc3BvbnNlX3ZhcnMpIHsNCiAgICAjIERhdGEgcHJlcHJvY2Vzc2luZyBmb3IgcGxvdHRpbmcNCiAgICBkYXRhIDwtIGRhdGFzZXRzW1tkYXRhc2V0X25hbWVdXSAlPiUNCiAgICAgIG11dGF0ZShUaW1lX0NhdGVnb3J5ID0gY2FzZV93aGVuKA0KICAgICAgICB5ZWFyICVpbiUgYmVmb3JlX3llYXJzIH4gIkJlZm9yZSIsDQogICAgICAgIHllYXIgJWluJSBhZnRlcl95ZWFycyB+ICJBZnRlciIsDQogICAgICAgIFRSVUUgfiBOQV9jaGFyYWN0ZXJfDQogICAgICApKSAlPiUNCiAgICAgIGZpbHRlcihwb29sX2lkICE9ICJUb3RhbCIpICU+JQ0KICAgICAgbXV0YXRlKHJlc3BvbnNlX2FkanVzdGVkID0gY2FzZV93aGVuKA0KICAgICAgICAhIXN5bShyZXNwb25zZV92YXIpID09IDAgfiAwLjAwMSwNCiAgICAgICAgISFzeW0ocmVzcG9uc2VfdmFyKSA9PSAxIH4gMC45OTksDQogICAgICAgIFRSVUUgfiAhIXN5bShyZXNwb25zZV92YXIpDQogICAgICApKQ0KDQogICAgIyBEaXN0cmlidXRpb24gb2YgdGhlIHJlc3BvbnNlIHZhcmlhYmxlDQogICAgcHJpbnQoZ2dwbG90KGRhdGEsIGFlcyh4ID0gcmVzcG9uc2VfYWRqdXN0ZWQpKSArDQogICAgICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMzAsIGZpbGwgPSAiYmx1ZSIsIGFscGhhID0gMC43KSArDQogICAgICBnZW9tX2RlbnNpdHkoY29sb3IgPSAicmVkIiwgbGluZXdpZHRoID0gMSkgKw0KICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJEaXN0cmlidXRpb24gb2YiLCByZXNwb25zZV92YXIsICIoQWRqdXN0ZWQpIiwgImZvciIsIGRhdGFzZXRfbmFtZSksDQogICAgICAgICAgIHggPSBwYXN0ZShyZXNwb25zZV92YXIsICIoQWRqdXN0ZWQpIiksIHkgPSAiRnJlcXVlbmN5IikgKw0KICAgICAgdGhlbWVfbWluaW1hbCgpKQ0KDQojIEFkZCByZXNpZHVhbHMgYW5kIGZpdHRlZCB2YWx1ZXMgZm9yIGRpYWdub3N0aWNzDQppZiAoIWlzLm51bGwoYmV0YV9tb2RlbCkpIHsNCiAgIyBFeHRyYWN0IHRoZSBkYXRhIHVzZWQgaW4gdGhlIG1vZGVsDQogIG1vZGVsX2RhdGEgPC0gbW9kZWwuZnJhbWUoYmV0YV9tb2RlbCkNCiAgDQogICMgQWRkIHJlc2lkdWFscyBhbmQgZml0dGVkIHZhbHVlcyB0byB0aGUgbW9kZWwgZGF0YQ0KICBtb2RlbF9kYXRhIDwtIG1vZGVsX2RhdGEgJT4lDQogICAgbXV0YXRlKHJlc2lkdWFscyA9IHJlc2lkdWFscyhiZXRhX21vZGVsLCB0eXBlID0gInBlYXJzb24iKSwNCiAgICAgICAgICAgZml0dGVkID0gZml0dGVkKGJldGFfbW9kZWwpKQ0KICANCiAgIyBQZXJmb3JtIGRpYWdub3N0aWNzDQogICMgUmVzaWR1YWxzIGRpc3RyaWJ1dGlvbg0KICBwcmludChnZ3Bsb3QobW9kZWxfZGF0YSwgYWVzKHggPSByZXNpZHVhbHMpKSArDQogICAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDMwLCBmaWxsID0gImJsdWUiLCBhbHBoYSA9IDAuNykgKw0KICAgIGdlb21fZGVuc2l0eShjb2xvciA9ICJyZWQiLCBzaXplID0gMSkgKw0KICAgIGxhYnModGl0bGUgPSBwYXN0ZSgiUmVzaWR1YWxzIERpc3RyaWJ1dGlvbiBmb3IiLCByZXNwb25zZV92YXIsICJpbiIsIGRhdGFzZXRfbmFtZSksDQogICAgICAgICB4ID0gIlJlc2lkdWFscyIsIHkgPSAiRnJlcXVlbmN5IikgKw0KICAgIHRoZW1lX21pbmltYWwoKSkNCiAgDQogICMgRml0dGVkIHZzIHJlc2lkdWFscw0KICBwcmludChnZ3Bsb3QobW9kZWxfZGF0YSwgYWVzKHggPSBmaXR0ZWQsIHkgPSByZXNpZHVhbHMpKSArDQogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKw0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gInJlZCIpICsNCiAgICBsYWJzKHRpdGxlID0gcGFzdGUoIkZpdHRlZCB2cyBSZXNpZHVhbHMgZm9yIiwgcmVzcG9uc2VfdmFyLCAiaW4iLCBkYXRhc2V0X25hbWUpLA0KICAgICAgICAgeCA9ICJGaXR0ZWQgVmFsdWVzIiwgeSA9ICJSZXNpZHVhbHMiKSArDQogICAgdGhlbWVfbWluaW1hbCgpKQ0KfQ0KDQogIH0NCn0NCmBgYA0KDQpIZXJlIGlzIHRoYXQgYmFzaWMgaW50ZXJwcmV0YXRpb24gYXNzaXN0YW5jZSBmcm9tIGJlZm9yZSwgYnV0IGFsc28gcmVtZW1iZXIgdGhhdCB0aGVyZSBpcyBleHRyYSBudWFuY2Ugbm93IHlvdSBhcmUgZGVhbGluZyB3aXRoIHByb3BvcnRpb25zIG9mIHBvb2wgbGVuZ3RoIG9yIHByb3BvcnRpb24gb2YgcG9vbCBwbGFuIGFyZWEuDQoNCi0gIk9wdGltaXphdGlvbiBmYWlsZWQgdG8gY29udmVyZ2UuLi4iIElmIHlvdSBzZWUgdGhpcyB3YXJuaW5nLCBpdCBtYXkgYmUgdGhhdCB0aGVyZSB3ZXJlIDAgdmFsdWVzIGFjcm9zcyBhbiBlbnRpcmUgU2l0ZS4gVGhpcyBzaG91bGQgYmUgZmFpcmx5IGVhc3kgdG8gaW50ZXJwcmV0IHdpdGhvdXQgaW5mZXJlbnRpYWwgdGVzdHMuDQoNCi0gUXVhbnRpbGUgcmVzaWR1YWxzIG1lYXN1cmUgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgYWN0dWFsIGRhdGEgYW5kIHByZWRpY3RlZCB2YWx1ZXMuIFRoZSBtZWRpYW4gc2hvdWxkIGJlIGNsb3NlIHRvIDAuIEFsc28gY2hlY2sgdGhlIHJlc2lkdWFscyB2cyBmaXR0ZWQgcGxvdCB0byBlbnN1cmUgdGhlcmUgaXMgbm8gY2xlYXIgdHJlbmQgb3IgdW51c3VhbCBvdXRsaWVycw0KDQotIENvZWZmaWNpZW50cyAobWVhbiBtb2RlbCk6IHRoZXNlIGFyZSB0aGUgZWZmZWN0cyBvZiB0aGUgcHJlZGljdG9ycyAoc2l0ZSwgdGltZSkgb24gdGhlIHJlc3BvbnNlIHZhcmlhYmxlIChmaW5lIHNlZGltZW50IHByb3BvcnRpb24gaW4gcG9vbHMpLiAqKkxvb2sgZm9yIHNpZ25pZmljYW50IHAgdmFsdWVzIGluIHRoZSBsYXN0IGNvbHVtbiwgcGFydGljdWxhcmx5IGZvciB0aGUgU2l0ZVxfXF9cX1xfXF9cOlRpbWVcX0NhdGVnb3J5XF9cX1xfXF9cXyByb3csIHdoaWNoIGlzIHRoZSBpbnRlcmFjdGlvbiB0ZXJtIChpZiBzaWduaWZpY2FudCwgdGhpcyBtZWFucyB0aGUgcHJvcG9ydGlvbiBvZiBmaW5lcyBpbiByZXNpZHVhbCBwb29scyBjaGFuZ2VkIG92ZXIgdGltZSBkaWZmZXJlbnRseSBiZXR3ZWVuIHNpdGVzKSoqLiANCg0KLSBQaGkgY29lZmZpY2llbnRzOiB0aGVyZSBpcyBhIHAtdmFsdWUgaGVyZSBhcyB3ZWxsLCBidXQgdGhpcyByZWZlcnMgdG8gd2hldGhlciB0aGUgc3ByZWFkIG9mIHRoZSBkYXRhIGFyb3VuZCB0aGUgbWVhbiB3YXMgYW4gaW1wb3J0YW50IGZlYXR1cmUuIElmIHRoZSBwaGkgZXN0aW1hdGUgaXMgdmVyeSBoaWdoLCB0aGlzIG1lYW5zIHRoZSBkYXRhIHdhcyBjb25jZW50cmF0ZWQgYXJvdW5kIHRoZSBtZWFuIChmaW5lcyBwcm9wb3J0aW9uIGRvZXNuJ3QgZmx1Y3R1YXRlIG11Y2ggYmV0d2VlbiBzaXRlcy90aW1lcykuIENvbnNpZGVyIHBoaSBvZiAwLjEgdG8gYmUgc3ByZWFkIG91dCBkYXRhLCAxIHRvIGJlIG1vZGVyYXRlLCBhbmQgMTAgdG8gYmUgY29uY2VudHJhdGVkIGFyb3VuZCB0aGUgbWVhbi4NCg0KLSBQc2V1ZG8gUi1zcXVhcmVkOiB0aGlzIGlzIGhvdyBtdWNoIG9mIHRoZSB2YXJpYXRpb24gaW4gZmluZXMgaW4gcG9vbHMgY2FuIGJlIGV4cGxhaW5lZCBieSB0aGUgc2l0ZSBhbmQgdGltZSB2YXJpYWJsZXMuIE9mdGVuIGxvdyBpbiBlY29sb2dpY2FsIGNvbnRleHRzLg0KDQpOZXh0IHVwIGFyZSB0aGUgcHJvbWlzZWQgcGxvdHMgdGhhdCBzaG93IHRoZSBkaXN0cmlidXRpb24gb2YgZmluZXMgYW5kIGFxdWF0aWNzIGFjcm9zcyB0aGUgcmVhY2gsIHdoaWNoIHNob3VsZCBmYWNpbGl0YXRlIGludGVycHJldGF0aW9uLg0KDQojIENvbXBvc2l0ZSBGaWd1cmUNCg0KVGhpcyBmaWd1cmUganV4dGFwb3NlcyB0aGUgcGxvdHMgc2hvd2luZyB0aGUgcmVzaWR1YWwgc3VyZmFjZXMgd2l0aCB0aGUgcHJlc2VuY2UvYWJzZW5jZSByZWNvcmQgb2YgZmluZSBzZWRpbWVudHMsIGFuZCB3aXRoIHRoZSB3ZXR0ZWQgd2lkdGggcHJvcG9ydGlvbiBvZiB0aGUgdGhyZWUgY2F0ZWdvcmllcyBvZiBhcXVhdGljIHZlZ2V0YXRpb24uIFdoZXJlIGZhY3RvcnMgbGlrZSBleGNlc3Mgc2VkaW1lbnRhdGlvbiwgZXV0cm9waGljYXRpb24sIGludmFzaXZlIGFxdWF0aWNzLCBleGNlc3NpdmVseSBmbHVjdHVhdGluZyBkaXNzb2x2ZWQgb3h5Z2VuLCBhbmQvb3IgbGFjayBvZiBwb29sIGhhYml0YXQgaXMgYSBjb25jZXJuLCB0aGlzIGZpZ3VyZSBzaG91bGQgYmUgdXNlZnVsIHRvIHZpc3VhbGx5IGNvbXBhcmUgcmVhY2hlcyBvciB0cmFjayBjaGFuZ2VzIG92ZXIgdGltZS4gDQoNClJlbWVtYmVyIHRoYXQgaW4gYSBCQUNJIHN0dWR5IG91ciBwcmltYXJ5IGludGVyZXN0IGlzIHdoZXRoZXIgb3VyIHJlc3RvcmF0aW9uIHNpdGUgY2hhbmdlZCBpbiBhIGRpZmZlcmVudCB3YXkgdGhhbiB0aGUgY29udHJvbC9yZWZlcmVuY2Ugc2l0ZXMgY2hhbmdlZCBhY3Jvc3MgdGltZSAtIHRoaXMgaXMgbm90IGFsd2F5cyBlYXN5IHRvIHNlZSBpbiBmaWd1cmVzLCBzbyBjb25zaWRlciB0aGUgZmlndXJlIGFsb25nc2lkZSB0aGUgaW5mZXJlbnRpYWwgdGVzdCByZXN1bHRzIGZyb20gYWJvdmUuIEJlYXIgaW4gbWluZCB0aGF0IHRoZSBmaWd1cmUgcHJlc2VudHMgZGF0YSBieSB5ZWFyIHdoZXJlYXMgb3VyIGluZmVyZW50aWFsIHRlc3RzIGNvbnNpZGVyIGJlZm9yZSB2cyBhZnRlciB0aW1lIGNhdGVnb3JpZXMuDQoNCklmIHlvdSBoYXZlIHNldmVyYWwgc2l0ZXMveWVhcnMsIHlvdSBjYW4gbW9kaWZ5IHRoZSBjb2RlIGJlbG93IHRvIGNob29zZSB3aGljaCBmaWd1cmVzIGFyZSBwbG90dGVkIGluIFJTdHVkaW8uIElmIGxlZnQgYXQgTlVMTCBzaXRlIGFuZCBOVUxMIHllYXIsIHRoZSBjb2RlIHdpbGwgZGlzcGxheSBhbGwgc2l0ZS15ZWFycyBpbiBvbmUgY29tcG9zaXRlIGZpZ3VyZS4gWW91IGNhbiBhbHRlciB0aGlzIGNvZGUgdG8gZGlzcGxheSBvbmUgeWVhciBmb3Igb25lIHNpdGUsIGFsbCB5ZWFycyBmb3Igb25lIHNpdGUsIG9yIGFsbCBzaXRlcyBmb3Igb25lIHllYXIuIA0KDQpSZWdhcmRsZXNzIG9mIHdoYXQgeW91IHZpZXcgaW4gUlN0dWRpbywgdGhlIGNvZGUgd2lsbCBleHBvcnQgYWxsIGluZGl2aWR1YWwgc2l0ZS15ZWFyIHBsb3RzIGFuZCB0aGUgZnVsbCBjb21wb3NpdGUgZmlndXJlIGFzIGh0bWwgZmlsZXMgdG8geW91ciBvdXRwdXQgZm9sZGVyLg0KDQpgYGB7ciBzcGVjaWZ5IHNpdGUgYW5kIHllYXJ9DQojIFVzZXItZGVmaW5lZCBzaXRlIGFuZCB5ZWFyIGZvciBpbmRpdmlkdWFsIHBsb3QgZGlzcGxheQ0Kc2VsZWN0ZWRfc2l0ZSA8LSBOVUxMICMgUmVwbGFjZSB3aXRoIHRoZSBkZXNpcmVkICJzaXRlIG5hbWUiIChpbmNsdWRlIHRoZSBxdW90YXRpb24gbWFya3MpIG9yIHVzZSBOVUxMIGZvciBhbGwgc2l0ZXMNCnNlbGVjdGVkX3llYXIgPC0gTlVMTCAjIFJlcGxhY2Ugd2l0aCB0aGUgZGVzaXJlZCB5ZWFyIChubyBicmFja2V0cykgb3IgdXNlIE5VTEwgZm9yIGFsbCB5ZWFycw0KYGBgDQoNCmBgYHtyIGZ1bmN0aW9uIGNyZWF0aW5nIHNlcGFyYXRlIG11bHRpcGxvdHMgZm9yIGVhY2ggc2l0ZS15ZWFyLCBlY2hvPUZBTFNFfQ0KIyBDb252ZXJ0ICd5ZWFyJyBpbiBkYXRhZnJhbWVzIHRvIG51bWVyaWMgKGlmIGZhY3RvciwgbWF5IGNhdXNlIGZpbHRlcmluZyBpc3N1ZXMpDQpyZXNpZHVhbHMuZGYgPC0gcmVzaWR1YWxzLmRmICU+JQ0KICBtdXRhdGUoeWVhciA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHllYXIpKSkNCg0KIyBDYWxjdWxhdGUgdGhlIGdsb2JhbCB5LWF4aXMgbGltaXRzIGZvciBEZXB0aCAobSkgYWNyb3NzIHRoZSBlbnRpcmUgZGF0YXNldCwgZm9yIHZpc3VhbCBjb21wYXJpc29uIG9uIHNhbWUgc2NhbGVkIHktYXhlcw0KZ2xvYmFsX2RlcHRoX2xpbWl0cyA8LSByZXNpZHVhbHMuZGYgJT4lDQogIGZpbHRlcihkaXN0YW5jZSA+PSAwKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGdsb2JhbF9taW5fZGVwdGggPSAwLCAgIyBrZWVwIG1pbiBkZXB0aCBhdCAwDQogICAgZ2xvYmFsX21heF9kZXB0aCA9IG1heChUaGFsd2VnX0RlcHRoX20sIG5hLnJtID0gVFJVRSkgICAjIENhbGN1bGF0ZSBtYXhpbXVtIGRlcHRoIGZyb20gdGhlIGRhdGENCiAgKQ0KDQojIEZ1bmN0aW9uIHRvIGdlbmVyYXRlIHRoZSBwbG90cyBmb3IgYSBnaXZlbiBzaXRlLXllYXIgY29tYmluYXRpb24NCmdlbmVyYXRlX3NpdGVfeWVhcl9wbG90cyA8LSBmdW5jdGlvbihyZXNpZHVhbHMuZGYsIHNpdGUsIHNlbGVjdGVkX3llYXIsIGdsb2JhbF9taW5fZGVwdGgsIGdsb2JhbF9tYXhfZGVwdGgpIHsNCiAgDQogICMgRmlsdGVyIGRhdGEgZm9yIHRoZSBzcGVjaWZpYyBzaXRlIGFuZCB5ZWFyIChpc29sYXRlZCBoZXJlKQ0KICBzaXRlX3llYXJfZGF0YSA8LSByZXNpZHVhbHMuZGYgJT4lDQogICAgZmlsdGVyKA0KICAgICAgICB0cmltd3MoU2l0ZSkgPT0gdHJpbXdzKHNpdGUpICYgDQogICAgICAgIHllYXIgPT0gYXMubnVtZXJpYyhzZWxlY3RlZF95ZWFyKSAmIA0KICAgICAgICBkaXN0YW5jZSA+PSAwDQogICAgKSAlPiUNCiAgICBtdXRhdGUoRmluZXNfcHJlc2VuY2UgPSBpZmVsc2UodG9sb3dlcihGaW5lcykgJWluJSBjKCJ5IiwgInllcyIpLCAxLCAwKSkNCiAgDQogICMgRGVmaW5lIGNvbnNpc3RlbnQgeC1heGlzIGxpbWl0cyAoc2hvdWxkIGJlIGJhc2VkIG9uIHRoZSBmaWx0ZXJlZCBkYXRhKQ0KICB4X2xpbWl0cyA8LSByYW5nZShzaXRlX3llYXJfZGF0YSRkaXN0YW5jZSwgbmEucm0gPSBUUlVFKQ0KICANCiAgIyBQbG90IDE6IFRoYWx3ZWcgRGVwdGggYW5kIFJlc2lkdWFsIFN1cmZhY2Ugd2l0aCBzdGFuZGFyZGl6ZWQgeS1heGlzDQogIHBsb3RfcmVzaWR1YWxzIDwtIHBsb3RfbHkoc2l0ZV95ZWFyX2RhdGEsIHggPSB+ZGlzdGFuY2UsIHkgPSB+VGhhbHdlZ19EZXB0aF9tLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ2xpbmVzJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gJ1RoYWx3ZWcgRGVwdGgnLCBsaW5lID0gbGlzdChjb2xvciA9ICdibGFjaycsIHdpZHRoID0gMikpICU+JQ0KICAgIGFkZF90cmFjZSh5ID0gfnJlc2lkdWFsX3N1cmZhY2UsIG1vZGUgPSAnbGluZXMnLCBuYW1lID0gJ1Jlc2lkdWFsIFN1cmZhY2UnLCBsaW5lID0gbGlzdChjb2xvciA9ICdibHVlJywgd2lkdGggPSAyKSkgJT4lDQogICAgbGF5b3V0KA0KICAgICAgeWF4aXMgPSBsaXN0KA0KICAgICAgICB0aXRsZSA9ICJEZXB0aCAobSkiLCANCiAgICAgICAgcmFuZ2UgPSBjKGdsb2JhbF9tYXhfZGVwdGgsIGdsb2JhbF9taW5fZGVwdGgpLCAgIyBVc2UgZ2xvYmFsIGRlcHRoIGxpbWl0cw0KICAgICAgICBhdXRvcmFuZ2UgPSBGQUxTRQ0KICAgICAgKSwNCiAgICAgIHhheGlzID0gbGlzdChyYW5nZSA9IHhfbGltaXRzKSwNCiAgICAgIHNob3dsZWdlbmQgPSBUUlVFDQogICAgKQ0KICANCiAgIyBQbG90IDI6IFN1Ym1lcmdlZCBWZWdldGF0aW9uIFByb3BvcnRpb24NCiAgcGxvdF9zdWJ2ZWcgPC0gcGxvdF9seShzaXRlX3llYXJfZGF0YSwgeCA9IH5kaXN0YW5jZSwgeSA9IH5zdWJ2ZWcsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbGluZXMnLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gJ2RhcmtncmVlbicsIHdpZHRoID0gMiksIGZpbGwgPSAndG96ZXJveScsIGZpbGxjb2xvciA9ICdkYXJrZ3JlZW4nKSAlPiUNCiAgICBsYXlvdXQoDQogICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiU3VidmVnIFByb3BvcnRpb25hbCBDb3ZlciIsIHJhbmdlID0gYygwLCAxKSksDQogICAgICB4YXhpcyA9IGxpc3QocmFuZ2UgPSB4X2xpbWl0cyksDQogICAgICBzaG93bGVnZW5kID0gRkFMU0UNCiAgICApDQogIA0KICAjIFBsb3QgMzogRmxvYXRpbmcgVmVnZXRhdGlvbiBQcm9wb3J0aW9uDQogIHBsb3RfZmxvYXR2ZWcgPC0gcGxvdF9seShzaXRlX3llYXJfZGF0YSwgeCA9IH5kaXN0YW5jZSwgeSA9IH5mbG9hdHZlZywgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcycsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICdmb3Jlc3RncmVlbicsIHdpZHRoID0gMiksIGZpbGwgPSAndG96ZXJveScsIGZpbGxjb2xvciA9ICdmb3Jlc3RncmVlbicpICU+JQ0KICAgIGxheW91dCgNCiAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJGbG9hdHZlZyBQcm9wb3J0aW9uYWwgQ292ZXIiLCByYW5nZSA9IGMoMCwgMSkpLA0KICAgICAgeGF4aXMgPSBsaXN0KHJhbmdlID0geF9saW1pdHMpLA0KICAgICAgc2hvd2xlZ2VuZCA9IEZBTFNFDQogICAgKQ0KICANCiAgIyBQbG90IDQ6IEVtZXJnZW50IFZlZ2V0YXRpb24gUHJvcG9ydGlvbg0KICBwbG90X2VtZXJndmVnIDwtIHBsb3RfbHkoc2l0ZV95ZWFyX2RhdGEsIHggPSB+ZGlzdGFuY2UsIHkgPSB+ZW1lcmd2ZWcsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbGluZXMnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAnbGlnaHRncmVlbicsIHdpZHRoID0gMiksIGZpbGwgPSAndG96ZXJveScsIGZpbGxjb2xvciA9ICdsaWdodGdyZWVuJykgJT4lDQogICAgbGF5b3V0KA0KICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIkVtZXJndmVnIFByb3BvcnRpb25hbCBDb3ZlciIsIHJhbmdlID0gYygwLCAxKSksDQogICAgICB4YXhpcyA9IGxpc3QocmFuZ2UgPSB4X2xpbWl0cyksDQogICAgICBzaG93bGVnZW5kID0gRkFMU0UNCiAgICApDQogIA0KICAjIFBsb3QgNTogRmluZXMgUHJlc2VuY2UvQWJzZW5jZQ0KICBwbG90X2ZpbmVzIDwtIHBsb3RfbHkoc2l0ZV95ZWFyX2RhdGEsIHggPSB+ZGlzdGFuY2UsIHkgPSB+RmluZXNfcHJlc2VuY2UsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbGluZXMnLA0KICAgICAgICAgICAgICAgICAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAnYnVybHl3b29kMycsIHdpZHRoID0gMiksIGZpbGwgPSAndG96ZXJveScsIGZpbGxjb2xvciA9ICdidXJseXdvb2QzJykgJT4lDQogICAgbGF5b3V0KA0KICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIkZpbmUgU2VkaW1lbnRzIiwgdGlja3ZhbHMgPSBjKDAsIDEpLCB0aWNrdGV4dCA9IGMoJ2FicycsICdwcmVzJyksIHJhbmdlID0gYygwLCAxKSksDQogICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiZGlzdGFuY2UgKG0pIiwgcmFuZ2UgPSB4X2xpbWl0cyksDQogICAgICBzaG93bGVnZW5kID0gRkFMU0UNCiAgICApDQogIA0KICAjIENvbWJpbmUgdGhlIHBsb3RzIGludG8gYSB2ZXJ0aWNhbCBncmlkDQogIHN1YnBsb3QoDQogICAgcGxvdF9yZXNpZHVhbHMgJT4lIGxheW91dCgNCiAgICAgIHlheGlzID0gbGlzdCgNCiAgICAgICAgdGl0bGUgPSAiRGVwdGggKG0pIiwgDQogICAgICAgIHJhbmdlID0gYyhnbG9iYWxfbWF4X2RlcHRoLCBnbG9iYWxfbWluX2RlcHRoKSwgICMgRW5zdXJlIGRlcHRoIGF4aXMgaXMgc2hhcmVkDQogICAgICAgIGF1dG9yYW5nZSA9IEZBTFNFLCANCiAgICAgICAgYXV0b21hcmdpbiA9IFRSVUUNCiAgICAgICkNCiAgICApLA0KICAgIHBsb3RfZW1lcmd2ZWcgJT4lIGxheW91dCh5YXhpcyA9IGxpc3QodGl0bGUgPSAiRW1lcmdlbnQgVmVnXG5Qcm9wb3J0aW9uYWwgQ292ZXIiLCByYW5nZSA9IGMoMCwgMSksIGF1dG9tYXJnaW4gPSBUUlVFKSksDQogICAgcGxvdF9mbG9hdHZlZyAlPiUgbGF5b3V0KHlheGlzID0gbGlzdCh0aXRsZSA9ICJGbG9hdGluZyBWZWdcblByb3BvcnRpb25hbCBDb3ZlciIsIHJhbmdlID0gYygwLCAxKSwgYXV0b21hcmdpbiA9IFRSVUUpKSwNCiAgICBwbG90X3N1YnZlZyAlPiUgbGF5b3V0KHlheGlzID0gbGlzdCh0aXRsZSA9ICJTdWJtZXJnZWQgVmVnXG5Qcm9wb3J0aW9uYWwgQ292ZXIiLCByYW5nZSA9IGMoMCwgMSksIGF1dG9tYXJnaW4gPSBUUlVFKSksDQogICAgcGxvdF9maW5lcyAlPiUgbGF5b3V0KHlheGlzID0gbGlzdCh0aXRsZSA9ICJGaW5lXG5TZWRpbWVudCIsIHRpY2t2YWxzID0gYygwLCAxKSwgdGlja3RleHQgPSBjKCJBYnMiLCAiUHJlcyIpLCBhdXRvbWFyZ2luID0gVFJVRSkpLA0KICAgIG5yb3dzID0gNSwNCiAgICBoZWlnaHRzID0gYygwLjUsIDAuMTI1LCAwLjEyNSwgMC4xMjUsIDAuMTI1KSwNCiAgICBzaGFyZVggPSBUUlVFLA0KICAgIHNoYXJlWSA9IFRSVUUgICMgU2hhcmUgeS1heGlzIGFjcm9zcyBhbGwgcGxvdHMNCiAgKSAlPiUNCiAgbGF5b3V0KA0KICAgIHRpdGxlID0gcGFzdGUoc2l0ZSwgc2VsZWN0ZWRfeWVhciwgIlRoYWx3ZWcgTG9uZ2l0dWRpbmFsIFByb2ZpbGUiKSwNCiAgICBtYXJnaW4gPSBsaXN0KHQgPSA1MCwgbCA9IDUwLCBiID0gNTApLCAgIyBJbmNyZWFzZSBsZWZ0IG1hcmdpbg0KICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJkaXN0YW5jZSAobSkiKSwgICMgU2hhcmVkIHgtYXhpcyBsYWJlbA0KICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJEZXB0aCAobSkiLCBhdXRvbWFyZ2luID0gVFJVRSwgdGl0bGVmb250ID0gbGlzdChzaXplPTEwKSksDQogICAgeWF4aXMyID0gbGlzdCh0aXRsZSA9ICJFbWVyZ1xuQ292ZXIiLCBhdXRvbWFyZ2luID0gVFJVRSwgdGl0bGVmb250ID0gbGlzdChzaXplPTEwKSksDQogICAgeWF4aXMzID0gbGlzdCh0aXRsZSA9ICJGbG9hdFxuQ292ZXIiLCBhdXRvbWFyZ2luID0gVFJVRSwgdGl0bGVmb250ID0gbGlzdChzaXplPTEwKSksDQogICAgeWF4aXM0ID0gbGlzdCh0aXRsZSA9ICJTdWJcbkNvdmVyIiwgYXV0b21hcmdpbiA9IFRSVUUsIHRpdGxlZm9udCA9IGxpc3Qoc2l6ZT0xMCkpLA0KICAgIHlheGlzNSA9IGxpc3QodGl0bGUgPSAiRmluZXMiLCBhdXRvbWFyZ2luID0gVFJVRSwgdGl0bGVmb250ID0gbGlzdChzaXplPTEwKSkNCiAgKQ0KfQ0KDQojIEdlbmVyYXRlIHVuaXF1ZSBzaXRlLXllYXIgY29tYmluYXRpb25zDQpzaXRlX3llYXJfY29tYmluYXRpb25zIDwtIHJlc2lkdWFscy5kZiAlPiUNCiAgZGlzdGluY3QoU2l0ZSwgeWVhcikgJT4lDQogIGFycmFuZ2UoU2l0ZSwgeWVhcikNCg0KIyBEaXNwbGF5IGVpdGhlciB0aGUgc2VsZWN0ZWQgc2l0ZS15ZWFyIHBsb3Qgb3IgYWxsIGNvbXBvc2l0ZSBwbG90cw0KaWYgKCFpcy5udWxsKHNlbGVjdGVkX3NpdGUpICYgIWlzLm51bGwoc2VsZWN0ZWRfeWVhcikpIHsNCiAgIyBDYXNlIDE6IFNwZWNpZmljIHNpdGUteWVhciBwbG90DQogIHNlbGVjdGVkX3Bsb3QgPC0gZ2VuZXJhdGVfc2l0ZV95ZWFyX3Bsb3RzKA0KICAgIHJlc2lkdWFscy5kZiwgc2VsZWN0ZWRfc2l0ZSwgc2VsZWN0ZWRfeWVhciwNCiAgICBnbG9iYWxfZGVwdGhfbGltaXRzJGdsb2JhbF9taW5fZGVwdGgsIGdsb2JhbF9kZXB0aF9saW1pdHMkZ2xvYmFsX21heF9kZXB0aA0KICApDQogIHNlbGVjdGVkX3Bsb3QgICMgRGlzcGxheSB0aGUgcGxvdCBpbiBSU3R1ZGlvDQoNCn0gZWxzZSBpZiAoIWlzLm51bGwoc2VsZWN0ZWRfc2l0ZSkgJiBpcy5udWxsKHNlbGVjdGVkX3llYXIpKSB7DQogICMgQ2FzZSAyOiBBbGwgeWVhcnMgZm9yIGEgc3BlY2lmaWMgc2l0ZQ0KICBzaXRlX3Bsb3RzIDwtIHNpdGVfeWVhcl9jb21iaW5hdGlvbnMgJT4lDQogICAgZmlsdGVyKFNpdGUgPT0gc2VsZWN0ZWRfc2l0ZSkgJT4lDQogICAgcG1hcF9kZnIoZnVuY3Rpb24oU2l0ZSwgeWVhcikgew0KICAgICAgcGxvdCA8LSBnZW5lcmF0ZV9zaXRlX3llYXJfcGxvdHMoDQogICAgICAgIHJlc2lkdWFscy5kZiwgU2l0ZSwgeWVhciwNCiAgICAgICAgZ2xvYmFsX2RlcHRoX2xpbWl0cyRnbG9iYWxfbWluX2RlcHRoLCBnbG9iYWxfZGVwdGhfbGltaXRzJGdsb2JhbF9tYXhfZGVwdGgNCiAgICAgICkNCiAgICAgIHRpYmJsZShwbG90ID0gbGlzdChwbG90KSwgeWVhciA9IHllYXIpDQogICAgfSkNCiAgDQogICMgQXJyYW5nZSBwbG90cyBmb3IgdGhlIHNpdGUgYWNyb3NzIGFsbCB5ZWFycw0KICBjb21iaW5lZF9zaXRlX3Bsb3QgPC0gc3VicGxvdCgNCiAgICBsYXBwbHkoc2l0ZV9wbG90cyRwbG90LCBpZGVudGl0eSksDQogICAgbnJvd3MgPSBucm93KHNpdGVfcGxvdHMpLCAgIyBPbmUgcm93IHBlciB5ZWFyDQogICAgdGl0bGVYID0gRkFMU0UsDQogICAgdGl0bGVZID0gVFJVRQ0KICApICU+JQ0KICAgIGxheW91dCh0aXRsZSA9IHBhc3RlKCJQbG90cyBmb3IgU2l0ZToiLCBzZWxlY3RlZF9zaXRlKSkNCiAgY29tYmluZWRfc2l0ZV9wbG90ICAjIERpc3BsYXkgdGhlIHBsb3QNCg0KfSBlbHNlIGlmIChpcy5udWxsKHNlbGVjdGVkX3NpdGUpICYgIWlzLm51bGwoc2VsZWN0ZWRfeWVhcikpIHsNCiAgIyBDYXNlIDM6IEFsbCBzaXRlcyBmb3IgYSBzcGVjaWZpYyB5ZWFyDQogIHllYXJfcGxvdHMgPC0gc2l0ZV95ZWFyX2NvbWJpbmF0aW9ucyAlPiUNCiAgICBmaWx0ZXIoeWVhciA9PSBzZWxlY3RlZF95ZWFyKSAlPiUNCiAgICBwbWFwX2RmcihmdW5jdGlvbihTaXRlLCB5ZWFyKSB7DQogICAgICBwbG90IDwtIGdlbmVyYXRlX3NpdGVfeWVhcl9wbG90cygNCiAgICAgICAgcmVzaWR1YWxzLmRmLCBTaXRlLCB5ZWFyLA0KICAgICAgICBnbG9iYWxfZGVwdGhfbGltaXRzJGdsb2JhbF9taW5fZGVwdGgsIGdsb2JhbF9kZXB0aF9saW1pdHMkZ2xvYmFsX21heF9kZXB0aA0KICAgICAgKQ0KICAgICAgdGliYmxlKHBsb3QgPSBsaXN0KHBsb3QpLCBzaXRlID0gU2l0ZSkNCiAgICB9KQ0KICANCiAgIyBBcnJhbmdlIHBsb3RzIGZvciB0aGUgeWVhciBhY3Jvc3MgYWxsIHNpdGVzDQogIGNvbWJpbmVkX3llYXJfcGxvdCA8LSBzdWJwbG90KA0KICAgIGxhcHBseSh5ZWFyX3Bsb3RzJHBsb3QsIGlkZW50aXR5KSwNCiAgICBucm93cyA9IG5yb3coeWVhcl9wbG90cyksICAjIE9uZSByb3cgcGVyIHNpdGUNCiAgICB0aXRsZVggPSBGQUxTRSwNCiAgICB0aXRsZVkgPSBUUlVFDQogICkgJT4lDQogICAgbGF5b3V0KHRpdGxlID0gcGFzdGUoIlBsb3RzIGZvciBZZWFyOiIsIHNlbGVjdGVkX3llYXIpKQ0KICBjb21iaW5lZF95ZWFyX3Bsb3QgICMgRGlzcGxheSB0aGUgcGxvdA0KDQp9IGVsc2Ugew0KICAjIENhc2UgNDogQWxsIHNpdGUteWVhciBjb21iaW5hdGlvbnMgDQogIGNvbXBvc2l0ZV9wbG90cyA8LSBzaXRlX3llYXJfY29tYmluYXRpb25zICU+JQ0KICAgIHBtYXBfZGZyKGZ1bmN0aW9uKFNpdGUsIHllYXIpIHsNCiAgICAgIHBsb3QgPC0gZ2VuZXJhdGVfc2l0ZV95ZWFyX3Bsb3RzKA0KICAgICAgICByZXNpZHVhbHMuZGYsIFNpdGUsIHllYXIsDQogICAgICAgIGdsb2JhbF9kZXB0aF9saW1pdHMkZ2xvYmFsX21pbl9kZXB0aCwgZ2xvYmFsX2RlcHRoX2xpbWl0cyRnbG9iYWxfbWF4X2RlcHRoDQogICAgICApDQogICAgICB0aWJibGUocGxvdCA9IGxpc3QocGxvdCksIHNpdGUgPSBTaXRlLCB5ZWFyID0geWVhcikNCiAgICB9KQ0KICANCiAgIyBHcm91cCBwbG90cyBieSBzaXRlDQogIHNpdGVfcGxvdHMgPC0gY29tcG9zaXRlX3Bsb3RzICU+JQ0KICAgIGdyb3VwX2J5KHNpdGUpICU+JQ0KICAgIGdyb3VwX21hcChmdW5jdGlvbihzaXRlX3Bsb3RzLCBzaXRlKSB7DQogICAgICBzdWJwbG90KA0KICAgICAgICBsYXBwbHkoc2l0ZV9wbG90cyRwbG90LCBpZGVudGl0eSksDQogICAgICAgIG5yb3dzID0gMSwgICMgT25lIHJvdyBmb3IgZWFjaCBzaXRlDQogICAgICAgIHRpdGxlWCA9IEZBTFNFLA0KICAgICAgICB0aXRsZVkgPSBUUlVFDQogICAgICApICU+JQ0KICAgICAgICBsYXlvdXQodGl0bGUgPSBsaXN0KHRleHQgPSBzaXRlLCBmb250ID0gbGlzdChzaXplID0gMTYpKSkNCiAgICB9KQ0KICANCiAgIyBDb21iaW5lIGFsbCBzaXRlIHJvd3MNCiAgY29tYmluZWRfcGxvdCA8LSBzdWJwbG90KA0KICAgIHNpdGVfcGxvdHMsDQogICAgbnJvd3MgPSBsZW5ndGgoc2l0ZV9wbG90cyksICAjIE9uZSByb3cgcGVyIHNpdGUNCiAgICB0aXRsZVggPSBUUlVFLA0KICAgIHRpdGxlWSA9IFRSVUUNCiAgKSAlPiUNCiAgICBsYXlvdXQodGl0bGUgPSAiTG9uZyBQcm9maWxlIENvbXBvc2l0ZSBQbG90cyBieSBTaXRlLVllYXIiKQ0KICANCiAgY29tYmluZWRfcGxvdCAgIyBEaXNwbGF5IHRoZSBjb21iaW5lZCBwbG90DQp9DQoNCiMgRXhwb3J0IEFMTCBpbmRpdmlkdWFsIHNpdGUteWVhciBwbG90cyBhcyBIVE1MDQppbnZpc2libGUoc2l0ZV95ZWFyX2NvbWJpbmF0aW9ucyAlPiUNCiAgcG1hcChmdW5jdGlvbihTaXRlLCB5ZWFyKSB7DQogICAgcGxvdCA8LSBnZW5lcmF0ZV9zaXRlX3llYXJfcGxvdHMoDQogICAgICByZXNpZHVhbHMuZGYsIFNpdGUsIHllYXIsDQogICAgICBnbG9iYWxfZGVwdGhfbGltaXRzJGdsb2JhbF9taW5fZGVwdGgsIGdsb2JhbF9kZXB0aF9saW1pdHMkZ2xvYmFsX21heF9kZXB0aA0KICAgICkNCiAgICANCiAgICAjIFNhdmUgZWFjaCBpbmRpdmlkdWFsIHBsb3QgYXMgYW4gSFRNTCBmaWxlDQogICAgZXhwb3J0X3Bsb3QocGxvdCwgcGFzdGUwKCJMb25nIFByb2ZpbGUgQ29tcG9zaXRlICIsIFNpdGUsICJfIiwgeWVhciwgIi5odG1sIikpDQogIH0pDQopDQogIA0KI2V4cG9ydCBjb21iaW5lZCBwbG90IA0KaWYgKGV4aXN0cygiY29tYmluZWRfcGxvdCIpKSB7DQogIGV4cG9ydF9wbG90KGNvbWJpbmVkX3Bsb3QsICJMb25nIFByb2ZpbGUgQ29tcG9zaXRlIFBsb3QgQWxsIFNpdGUgWWVhcnMuaHRtbCIpDQp9DQpgYGANCg0KTm93IHRoYXQgeW91IGhhdmUgdmlzdWFsaXNhdGlvbnMgb2YgdGhlIHJlc2lkdWFsIHBvb2wgZGF0YSwgYW5kIHN0YXRpc3RpY2FsIHRlc3RzIHRvIGV4YW1pbmUgdGhlIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZSBvZiBkaWZmZXJlbmNlcyBpbiByZWFjaCBwb29sIGNoYXJhY3RlcmlzdGljcyBhbW9uZyByZWFjaGVzIGFuZCB5ZWFycywgaXQgaXMgdGltZSB0byBjb25zaWRlciB0aGUgYmlvbG9naWNhbC9tb3JwaG9sb2dpY2FsIHNpZ25pZmljYW5jZSBhbmQgdGhlIGltcGxpY2F0aW9ucyBmb3IgeW91ciBwcm9qZWN0Lg0KDQojIE5leHQgU3RlcHMNCg0KV2UgY2FuIG5vdyBtb3ZlIG9uIHRvIGxvb2tpbmcgYXQgYSBmZXcgbW9yZSBjb21wb25lbnRzIG9mIGhhYml0YXQgdGhhdCBtYXkgYmUgdXNlZnVsIHRvIG1vbml0b3IgZm9yIHlvdXIgcHJvamVjdC4gV2Ugd2lsbCBleHBvcnQgdGhlIHJlc2lkdWFsIHBvb2wgZGF0YSB3ZSBnZW5lcmF0ZWQgaW4gdGhpcyBjb2RlIGZvciB1c2UgbGF0ZXIgb24gKHdoZW4gY29uc2lkZXJpbmcgaGFiaXRhdCB1bml0IGNsYXNzaWZpY2F0aW9ucykuIFRoaXMgd2lsbCBiZSBleHBvcnRlZCB0byB5b3VyIG91dHB1dCBmb2xkZXIgKHdoaWNoIGJ5IG5vdywgbWlnaHQgYmUgYSBiaXQgYnVzeS4gSWYgbW92aW5nIGZpbGVzIGFyb3VuZCwgcmVtZW1iZXIgdGhhdCB0aGUgaHRtbCBmaWxlcyBuZWVkIHRvIGJlIGluIHRoZSBzYW1lIGZvbGRlciBhcyB0aGVpciBzaW1pbGFybHktbmFtZWQgZGVwZW5kZW5jeSBmb2xkZXJzKS4NCg0KYGBge3IgcmVzaWR1YWxzLmRmIGV4cG9ydCwgZWNobz1GQUxTRX0NCmV4cG9ydF90YWJsZShhcy5kYXRhLmZyYW1lKHJlc2lkdWFscy5kZiksIlJlc2lkdWFsc19kYXRhZnJhbWUuY3N2IikNCmBgYA0KDQojIFJlZmVyZW5jZXMgDQoNCkNsYXJrLCBDLiwgUm9uaSwgUC4gYW5kIEJ1cmdlc3MsIFMuLCAyMDE5LiBSZXNwb25zZSBvZiBqdXZlbmlsZSBzYWxtb25pZHMgdG8gbGFyZ2Ugd29vZCBwbGFjZW1lbnQgaW4gQ29sdW1iaWEgUml2ZXIgdHJpYnV0YXJpZXMuIEh5ZHJvYmlvbG9naWEsIDg0MigxKSwgcHAuMTczLTE5MC4NCg0KR2Vpc3NpbmdlciwgRS5BLiwgS2hvbywgQy5MLiwgUmljaG1vbmQsIEkuQy4sIEZhdWxrbmVyLCBTLkouIGFuZCBTY2huZWlkZXIsIEQuQy4sIDIwMjIuIEEgY2FzZSBmb3IgYmV0YSByZWdyZXNzaW9uIGluIHRoZSBuYXR1cmFsIHNjaWVuY2VzLiBFY29zcGhlcmUsIDEzKDIpLCBwLmUzOTQwLg0KDQpLYXVmbWFubiwgUC5SLiwgTGV2aW5lLCBQLiwgUGVjaywgRC5WLiwgUm9iaXNvbiwgRS5HLiBhbmQgU2VlbGlnZXIsIEMuLCAxOTk5LiBRdWFudGlmeWluZyBwaHlzaWNhbCBoYWJpdGF0IGluIHdhZGVhYmxlIHN0cmVhbXMgKHAuIDE0OSkuIFVTRVBBIFtOYXRpb25hbCBIZWFsdGggYW5kIEVudmlyb25tZW50YWwgRWZmZWN0cyBSZXNlYXJjaCBMYWJvcmF0b3J5LCBXZXN0ZXJuIEVjb2xvZ3kgRGl2aXNpb25dLg0KDQpMaXNsZSwgVC5FLiwgMTk4Ni4gRWZmZWN0cyBvZiB3b29keSBkZWJyaXMgb24gYW5hZHJvbW91cyBzYWxtb25pZCBoYWJpdGF0LCBQcmluY2Ugb2YgV2FsZXMgSXNsYW5kLCBzb3V0aGVhc3QgQWxhc2thLiBOb3J0aCBBbWVyaWNhbiBKb3VybmFsIG9mIEZpc2hlcmllcyBNYW5hZ2VtZW50LCA2KDQpLCBwcC41MzgtNTUwLg0KDQpMaXNsZSwgVC5FLiwgMTk4Ny4gVXNpbmciIHJlc2lkdWFsIGRlcHRocyIgdG8gbW9uaXRvciBwb29sIGRlcHRocyBpbmRlcGVuZGVudGx5IG9mIGRpc2NoYXJnZS4gUmVzLiBOb3RlIFBTVy1STi0zOTQuIEJlcmtlbGV5LCBDQTogVVMgRGVwYXJ0bWVudCBvZiBBZ3JpY3VsdHVyZSwgRm9yZXN0IFNlcnZpY2UsIFBhY2lmaWMgU291dGh3ZXN0IEZvcmVzdCBhbmQgUmFuZ2UgRXhwZXJpbWVudCBTdGF0aW9uLiA0IHAsIDM5NC4NCg0KTW9zc29wLCBCLiBhbmQgQnJhZGZvcmQsIE0uSi4sIDIwMDYuIFVzaW5nIHRoYWx3ZWcgcHJvZmlsaW5nIHRvIGFzc2VzcyBhbmQgbW9uaXRvciBqdXZlbmlsZSBzYWxtb24gKE9uY29yaHluY2h1cyBzcHAuKSBoYWJpdGF0IGluIHNtYWxsIHN0cmVhbXMuIENhbmFkaWFuIEpvdXJuYWwgb2YgRmlzaGVyaWVzIGFuZCBBcXVhdGljIFNjaWVuY2VzLCA2Myg3KSwgcHAuMTUxNS0xNTI1Lg0KDQpSb2Jpc29uLCBFLkcuLCAxOTk4LiBSZWFjaCBzY2FsZSBzYW1wbGluZyBtZXRyaWNzIGFuZCBsb25naXR1ZGluYWwgcGF0dGVybiBhZGp1c3RtZW50IG9mIHNtYWxsIHN0cmVhbXMuIFBoRCBUaGVzaXMuIE9yZWdvbiBTdGF0ZSBVbml2ZXJzaXR5Lg0KDQpTdGFjaywgVy5SLiwgMTk4OC4gRmFjdG9ycyBpbmZsdWVuY2luZyBwb29sIG1vcnBob2xvZ3kgaW4gT3JlZ29uIGNvYXN0YWwgc3RyZWFtcy4gTVNjIFRoZXNpcy4gT3JlZ29uIFN0YXRlIFVuaXZlcnNpdHk=